Add type 12h sdr records
This adds support for BMC and ME type 12 records.
Tested:
ipmitool sdr list mcloc
Device ID : �Basbrd Mgmt Ctl
Entity ID : 0.46 (Unspecified)
Device Slave Address : 20h
Channel Number : 0h
ACPI System P/S Notif : Not Required
ACPI Device P/S Notif : Not Required
Controller Presence : Dynamic
Logs Init Agent Errors : No
Event Message Gen : Enable
Device Capabilities
Chassis Device : Yes
Bridge : No
IPMB Event Generator : Yes
IPMB Event Receiver : Yes
FRU Inventory Device : Yes
SEL Device : Yes
SDR Repository : Yes
Sensor Device : Yes
Device ID : �Mgmt Engin
Entity ID : 0.46 (Unspecified)
Device Slave Address : 2Ch
Channel Number : 6h
ACPI System P/S Notif : Not Required
ACPI Device P/S Notif : Not Required
Controller Presence : Static
Logs Init Agent Errors : No
Event Message Gen : Enable
Device Capabilities
Chassis Device : No
Bridge : No
IPMB Event Generator : Yes
IPMB Event Receiver : No
FRU Inventory Device : No
SEL Device : No
SDR Repository : No
Sensor Device : Yes
Change-Id: I3d015ca2f61ab07be18ba46239c3d6a919f0298b
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/include/storagecommands.hpp b/include/storagecommands.hpp
index 1a2d281..1c709d1 100644
--- a/include/storagecommands.hpp
+++ b/include/storagecommands.hpp
@@ -35,17 +35,6 @@
} // namespace intel_oem::ipmi::sel
#pragma pack(push, 1)
-struct GetSDRInfoResp
-{
- uint8_t sdrVersion;
- uint8_t recordCountLS;
- uint8_t recordCountMS;
- uint8_t freeSpace[2];
- uint32_t mostRecentAddition;
- uint32_t mostRecentErase;
- uint8_t operationSupport;
-};
-
struct GetSDRReq
{
uint16_t reservationID;
@@ -123,12 +112,33 @@
};
#pragma pack(pop)
+#pragma pack(push, 1)
+struct Type12Record
+{
+ get_sdr::SensorDataRecordHeader header;
+ uint8_t slaveAddress;
+ uint8_t channelNumber;
+ uint8_t powerStateNotification;
+ uint8_t deviceCapabilities;
+ uint24_t reserved;
+ uint8_t entityID;
+ uint8_t entityInstance;
+ uint8_t oem;
+ uint8_t typeLengthCode;
+ char name[16];
+};
+#pragma pack(pop)
+
namespace ipmi
{
namespace storage
{
+
+constexpr const size_t type12Count = 2;
ipmi_ret_t getFruSdrs(size_t index, get_sdr::SensorDataFruRecord& resp);
ipmi_ret_t getFruSdrCount(size_t& count);
+
+std::vector<uint8_t> getType12SDRs(uint16_t index, uint16_t recordId);
} // namespace storage
} // namespace ipmi
diff --git a/src/sensorcommands.cpp b/src/sensorcommands.cpp
index b24ac7e..28d68f4 100644
--- a/src/sensorcommands.cpp
+++ b/src/sensorcommands.cpp
@@ -1053,52 +1053,41 @@
/* storage commands */
-ipmi_ret_t ipmiStorageGetSDRRepositoryInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
- ipmi_request_t request,
- ipmi_response_t response,
- ipmi_data_len_t dataLen,
- ipmi_context_t context)
+ipmi::RspType<uint8_t, // sdr version
+ uint16_t, // record count
+ uint16_t, // free space
+ uint32_t, // most recent addition
+ uint32_t, // most recent erase
+ uint8_t // operationSupport
+ >
+ ipmiStorageGetSDRRepositoryInfo(void)
{
- printCommand(+netfn, +cmd);
-
- if (*dataLen)
- {
- *dataLen = 0;
- return IPMI_CC_REQ_DATA_LEN_INVALID;
- }
- *dataLen = 0; // default to 0 in case of an error
-
+ constexpr const uint16_t unspecifiedFreeSpace = 0xFFFF;
if (sensorTree.empty() && !getSensorSubtree(sensorTree))
{
- return IPMI_CC_RESPONSE_ERROR;
+ return ipmi::responseResponseError();
}
- // zero out response buff
- auto responseClear = static_cast<uint8_t *>(response);
- std::fill(responseClear, responseClear + sizeof(GetSDRInfoResp), 0);
+ size_t fruCount = 0;
+ ipmi::Cc ret = ipmi::storage::getFruSdrCount(fruCount);
+ if (ret != ipmi::ccSuccess)
+ {
+ return ipmi::response(ret);
+ }
- auto resp = static_cast<GetSDRInfoResp *>(response);
- resp->sdrVersion = ipmiSdrVersion;
- uint16_t recordCount = sensorTree.size();
+ uint16_t recordCount =
+ sensorTree.size() + fruCount + ipmi::storage::type12Count;
- // todo: for now, sdr count is number of sensors
- resp->recordCountLS = recordCount & 0xFF;
- resp->recordCountMS = recordCount >> 8;
-
- // free space unspcified
- resp->freeSpace[0] = 0xFF;
- resp->freeSpace[1] = 0xFF;
-
- resp->mostRecentAddition = sdrLastAdd;
- resp->mostRecentErase = sdrLastRemove;
- resp->operationSupport = static_cast<uint8_t>(
+ uint8_t operationSupport = static_cast<uint8_t>(
SdrRepositoryInfoOps::overflow); // write not supported
- resp->operationSupport |=
+
+ operationSupport |=
static_cast<uint8_t>(SdrRepositoryInfoOps::allocCommandSupported);
- resp->operationSupport |= static_cast<uint8_t>(
+ operationSupport |= static_cast<uint8_t>(
SdrRepositoryInfoOps::reserveSDRRepositoryCommandSupported);
- *dataLen = sizeof(GetSDRInfoResp);
- return IPMI_CC_OK;
+ return ipmi::responseSuccess(ipmiSdrVersion, recordCount,
+ unspecifiedFreeSpace, sdrLastAdd,
+ sdrLastRemove, operationSupport);
}
/** @brief implements the get SDR allocation info command
@@ -1166,13 +1155,14 @@
}
size_t fruCount = 0;
- ipmi_ret_t ret = ipmi::storage::getFruSdrCount(fruCount);
- if (ret != IPMI_CC_OK)
+ ipmi::Cc ret = ipmi::storage::getFruSdrCount(fruCount);
+ if (ret != ipmi::ccSuccess)
{
return ipmi::response(ret);
}
- size_t lastRecord = sensorTree.size() + fruCount - 1;
+ size_t lastRecord =
+ sensorTree.size() + fruCount + ipmi::storage::type12Count - 1;
if (recordID == lastRecordIndex)
{
recordID = lastRecord;
@@ -1186,30 +1176,51 @@
if (recordID >= sensorTree.size())
{
+ std::vector<uint8_t> recordData;
size_t fruIndex = recordID - sensorTree.size();
if (fruIndex >= fruCount)
{
- return ipmi::responseInvalidFieldRequest();
- }
- get_sdr::SensorDataFruRecord data;
- if (offset > sizeof(data))
- {
- return ipmi::responseInvalidFieldRequest();
- }
- ret = ipmi::storage::getFruSdrs(fruIndex, data);
- if (ret != IPMI_CC_OK)
- {
- return ipmi::response(ret);
- }
- data.header.record_id_msb = recordID << 8;
- data.header.record_id_lsb = recordID & 0xFF;
- if (sizeof(data) < (offset + bytesToRead))
- {
- bytesToRead = sizeof(data) - offset;
- }
+ // handle type 12 hardcoded records
+ size_t type12Index = fruIndex - fruCount;
+ if (type12Index >= ipmi::storage::type12Count ||
+ offset > sizeof(Type12Record))
+ {
+ return ipmi::responseInvalidFieldRequest();
+ }
+ std::vector<uint8_t> record =
+ ipmi::storage::getType12SDRs(type12Index, recordID);
+ if (record.size() < (offset + bytesToRead))
+ {
+ bytesToRead = record.size() - offset;
+ }
- uint8_t *respStart = reinterpret_cast<uint8_t *>(&data) + offset;
- std::vector<uint8_t> recordData(respStart, respStart + bytesToRead);
+ recordData.insert(recordData.end(), record.begin() + offset,
+ record.begin() + offset + bytesToRead);
+ }
+ else
+ {
+ // handle fru records
+ get_sdr::SensorDataFruRecord data;
+ if (offset > sizeof(data))
+ {
+ return ipmi::responseInvalidFieldRequest();
+ }
+ ret = ipmi::storage::getFruSdrs(fruIndex, data);
+ if (ret != IPMI_CC_OK)
+ {
+ return ipmi::response(ret);
+ }
+ data.header.record_id_msb = recordID << 8;
+ data.header.record_id_lsb = recordID & 0xFF;
+ if (sizeof(data) < (offset + bytesToRead))
+ {
+ bytesToRead = sizeof(data) - offset;
+ }
+
+ uint8_t *respStart = reinterpret_cast<uint8_t *>(&data) + offset;
+ recordData.insert(recordData.end(), respStart,
+ respStart + bytesToRead);
+ }
return ipmi::responseSuccess(nextRecordId, recordData);
}
@@ -1491,10 +1502,10 @@
// versions
// <Get SDR Repository Info>
- ipmiPrintAndRegister(
- NETFUN_STORAGE,
- static_cast<ipmi_cmd_t>(IPMINetfnStorageCmds::ipmiCmdGetRepositoryInfo),
- nullptr, ipmiStorageGetSDRRepositoryInfo, PRIVILEGE_USER);
+ ipmi::registerHandler(
+ ipmi::prioOemBase, NETFUN_STORAGE,
+ static_cast<ipmi::Cmd>(IPMINetfnStorageCmds::ipmiCmdGetRepositoryInfo),
+ ipmi::Privilege::User, ipmiStorageGetSDRRepositoryInfo);
// <Get SDR Allocation Info>
ipmi::registerHandler(
diff --git a/src/storagecommands.cpp b/src/storagecommands.cpp
index 39405c5..8c716c2 100644
--- a/src/storagecommands.cpp
+++ b/src/storagecommands.cpp
@@ -1022,6 +1022,62 @@
return ipmi::responseInvalidCommand();
}
+std::vector<uint8_t> getType12SDRs(uint16_t index, uint16_t recordId)
+{
+ std::vector<uint8_t> resp;
+ if (index == 0)
+ {
+ Type12Record bmc = {};
+ bmc.header.record_id_lsb = recordId;
+ bmc.header.record_id_msb = recordId >> 8;
+ bmc.header.sdr_version = ipmiSdrVersion;
+ bmc.header.record_type = 0x12;
+ bmc.header.record_length = 0x1b;
+ bmc.slaveAddress = 0x20;
+ bmc.channelNumber = 0;
+ bmc.powerStateNotification = 0;
+ bmc.deviceCapabilities = 0xBF;
+ bmc.reserved = 0;
+ bmc.entityID = 0x2E;
+ bmc.entityInstance = 1;
+ bmc.oem = 0;
+ bmc.typeLengthCode = 0xD0;
+ std::string bmcName = "Basbrd Mgmt Ctlr";
+ std::copy(bmcName.begin(), bmcName.end(), bmc.name);
+ uint8_t* bmcPtr = reinterpret_cast<uint8_t*>(&bmc);
+ resp.insert(resp.end(), bmcPtr, bmcPtr + sizeof(Type12Record));
+ }
+ else if (index == 1)
+ {
+ Type12Record me = {};
+ me.header.record_id_lsb = recordId;
+ me.header.record_id_msb = recordId >> 8;
+ me.header.sdr_version = ipmiSdrVersion;
+ me.header.record_type = 0x12;
+ me.header.record_length = 0x16;
+ me.slaveAddress = 0x2C;
+ me.channelNumber = 6;
+ me.powerStateNotification = 0x24;
+ me.deviceCapabilities = 0x21;
+ me.reserved = 0;
+ me.entityID = 0x2E;
+ me.entityInstance = 2;
+ me.oem = 0;
+ me.typeLengthCode = 0xCB;
+ std::string meName = "Mgmt Engine";
+ std::copy(meName.begin(), meName.end(), me.name);
+ uint8_t* mePtr = reinterpret_cast<uint8_t*>(&me);
+ resp.insert(resp.end(), mePtr, mePtr + sizeof(Type12Record));
+ }
+ else
+ {
+ throw std::runtime_error("getType12SDRs:: Illegal index " +
+ std::to_string(index));
+ }
+
+ return resp;
+}
+
void registerStorageFunctions()
{
// <Get FRU Inventory Area Info>