DCMI Commands: Support Get DCMI Sensor Info Dynamically
When Dynamic SDR Feature is enabled the sensor record id should be get dynamically for DCMI Sensors.
Tested:
Case 1:Get inlet sensor information
$ipmitool raw 0x2c 0x07 0xdc 0x01 0x40 0x00 0x00
dc 01 01 1a 00
Case 2:Get Baseboard sensor information
ipmitool raw 0x2c 0x07 0xdc 0x01 0x41 0x00 0x00
dc 02 02 18 00 19 00
Case 3:Get CPU sensor information
ipmitool raw 0x2c 0x07 0xdc 0x01 0x42 0x00 0x00
dc 01 01 1b 00
Case 4: Give a invalid sensor instance number
$ipmitool raw 0x2c 0x07 0xdc 0x01 0x41 0x05 0x00
Unable to send RAW command (channel=0x0 netfn=0x2c lun=0x0 cmd=0x7 rsp=0xff): Unspecified error
Result : The command should throw error
Case 5:Get a specific sensor details by giving instance parameter 2 of CPU sensors
$ipmitool raw 0x2c 0x07 0xdc 0x01 0x41 0x02 0x00
dc 02 01 19 00
Signed-off-by: adarshgrami <adarshgr@ami.com>
Change-Id: Ib2099a49ecaebc16b5fae29a4c18ca3e788aabf1
diff --git a/dbus-sdr/sensorcommands.cpp b/dbus-sdr/sensorcommands.cpp
index b356f93..4753a7b 100644
--- a/dbus-sdr/sensorcommands.cpp
+++ b/dbus-sdr/sensorcommands.cpp
@@ -54,7 +54,18 @@
} // namespace sensor
} // namespace ipmi
#endif
-
+namespace ipmi
+{
+namespace dcmi
+{
+// Refer Table 6-14, DCMI Entity ID Extension, DCMI v1.5 spec
+static const std::map<uint8_t, uint8_t> validEntityId{
+ {0x40, 0x37}, {0x37, 0x40}, {0x41, 0x03},
+ {0x03, 0x41}, {0x42, 0x07}, {0x07, 0x42}};
+constexpr uint8_t temperatureSensorType = 0x01;
+constexpr uint8_t maxRecords = 8;
+} // namespace dcmi
+} // namespace ipmi
constexpr std::array<const char*, 7> suffixes = {
"_Output_Voltage", "_Input_Voltage", "_Output_Current", "_Input_Current",
"_Output_Power", "_Input_Power", "_Temperature"};
@@ -2396,6 +2407,105 @@
return ipmi::responseSuccess(nextRecordId, recordData);
}
+namespace dcmi
+{
+
+ipmi::RspType<uint8_t, // No of instances for requested id
+ uint8_t, // No of record ids in the response
+ std::vector<uint16_t> // SDR Record ID corresponding to the Entity
+ // IDs
+ >
+ getSensorInfo(ipmi::Context::ptr ctx, uint8_t sensorType, uint8_t entityId,
+ uint8_t entityInstance, uint8_t instanceStart)
+{
+ auto match = ipmi::dcmi::validEntityId.find(entityId);
+ if (match == ipmi::dcmi::validEntityId.end())
+ {
+ log<level::ERR>("Unknown Entity ID", entry("ENTITY_ID=%d", entityId));
+
+ return ipmi::responseInvalidFieldRequest();
+ }
+
+ if (sensorType != ipmi::dcmi::temperatureSensorType)
+ {
+ log<level::ERR>("Invalid sensor type",
+ entry("SENSOR_TYPE=%d", sensorType));
+
+ return ipmi::responseInvalidFieldRequest();
+ }
+ auto& sensorTree = getSensorTree();
+ if (!getSensorSubtree(sensorTree) && sensorTree.empty())
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+
+ std::vector<uint16_t> sensorRec{};
+ uint8_t numInstances = 0;
+
+ for (const auto& sensor : sensorTree)
+ {
+ auto sensorTypeValue = getSensorTypeFromPath(sensor.first);
+ if (sensorTypeValue != ipmi::dcmi::temperatureSensorType)
+ {
+ continue;
+ }
+ const auto& connection = sensor.second.begin()->first;
+
+ DbusInterfaceMap sensorMap;
+ if (!getSensorMap(ctx, connection, sensor.first, sensorMap,
+ sensorMapSdrUpdatePeriod))
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Failed to update sensor map for threshold sensor",
+ phosphor::logging::entry("SERVICE=%s", connection.c_str()),
+ phosphor::logging::entry("PATH=%s", sensor.first.c_str()));
+ continue;
+ }
+ uint8_t entityIdValue = 0;
+ uint8_t entityInstanceValue = 0;
+
+ updateIpmiFromAssociation(sensor.first, sensorMap, entityIdValue,
+ entityInstanceValue);
+ if (!entityInstance)
+ {
+ if (entityIdValue == match->first || entityIdValue == match->second)
+ {
+ auto recordId = getSensorNumberFromPath(sensor.first);
+ if (recordId != invalidSensorNumber)
+ {
+ numInstances++;
+ if (numInstances <= ipmi::dcmi::maxRecords)
+ {
+ sensorRec.push_back(recordId);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (entityIdValue == match->first || entityIdValue == match->second)
+ {
+ if (entityInstance == entityInstanceValue)
+ {
+ auto recordId = getSensorNumberFromPath(sensor.first);
+ if ((recordId != invalidSensorNumber) && sensorRec.empty())
+ {
+ sensorRec.push_back(recordId);
+ }
+ }
+ numInstances++;
+ }
+ }
+ }
+ if (sensorRec.empty())
+ {
+ return ipmi::responseSensorInvalid();
+ }
+ uint8_t numRecords = sensorRec.size();
+ return ipmi::responseSuccess(numInstances, numRecords, sensorRec);
+}
+} // namespace dcmi
+
/* end storage commands */
void registerSensorFunctions()
@@ -2473,5 +2583,10 @@
ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
ipmi::storage::cmdGetSdr, ipmi::Privilege::User,
ipmiStorageGetSDR);
+ // <Get DCMI Sensor Info>
+ ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, ipmi::groupDCMI,
+ ipmi::dcmi::cmdGetDcmiSensorInfo,
+ ipmi::Privilege::User,
+ ipmi::dcmi::getSensorInfo);
}
} // namespace ipmi
diff --git a/dcmihandler.cpp b/dcmihandler.cpp
index 31f9224..3fd976f 100644
--- a/dcmihandler.cpp
+++ b/dcmihandler.cpp
@@ -1431,11 +1431,13 @@
// <Get Power Reading>
ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_POWER_READING,
NULL, getPowerReading, PRIVILEGE_USER);
-
+// The Get sensor should get the senor details dynamically when
+// FEATURE_DYNAMIC_SENSORS is enabled.
+#ifndef FEATURE_DYNAMIC_SENSORS
// <Get Sensor Info>
ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_SENSOR_INFO, NULL,
getSensorInfo, PRIVILEGE_USER);
-
+#endif
// <Get DCMI Configuration Parameters>
ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_CONF_PARAMS, NULL,
getDCMIConfParams, PRIVILEGE_USER);