summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Kodihalli <dkodihal@in.ibm.com>2018-02-06 06:25:12 -0600
committerTom Joseph <tomjoseph@in.ibm.com>2018-02-16 02:22:27 +0000
commit0b45955f5b0be301dee64083f51ffe9c34d3e153 (patch)
tree09ebf58943715d3a79a4489d6704dd0c780798a0
parent61d5f7bcd892b9f546ad5b19ad96238110602743 (diff)
downloadphosphor-host-ipmid-0b45955f5b0be301dee64083f51ffe9c34d3e153.tar.gz
phosphor-host-ipmid-0b45955f5b0be301dee64083f51ffe9c34d3e153.zip
dcmi: implement get sensor info
This commit implements the plumbing around the 'Get Sensor Info' command. It doesn't read the sensor information yet. That code is coming up in a subsequent commit. Refactor some of the get temperature readings code, in order to reuse certain common aspects for this commit. Change-Id: I0cb531b5b75e98cc9e76509f84f832be9997fee0 Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
-rw-r--r--dcmihandler.cpp186
-rw-r--r--dcmihandler.hpp100
-rw-r--r--host-ipmid-whitelist.conf1
3 files changed, 241 insertions, 46 deletions
diff --git a/dcmihandler.cpp b/dcmihandler.cpp
index bfc8466..54c8799 100644
--- a/dcmihandler.cpp
+++ b/dcmihandler.cpp
@@ -40,6 +40,18 @@ using namespace phosphor::logging;
namespace dcmi
{
+// Refer Table 6-14, DCMI Entity ID Extension, DCMI v1.5 spec
+static const std::map<uint8_t, std::string> entityIdToName
+{
+ {0x40, "inlet"},
+ {0x37, "inlet"},
+ {0x41, "cpu"},
+ {0x03, "cpu"},
+ {0x42, "baseboard"},
+ {0x07, "baseboard"}
+};
+
+
uint32_t getPcap(sdbusplus::bus::bus& bus)
{
auto settingService = ipmi::getService(bus,
@@ -232,6 +244,25 @@ std::string getHostName(void)
return value.get<std::string>();
}
+Json parseSensorConfig()
+{
+ std::ifstream jsonFile(configFile);
+ if (!jsonFile.is_open())
+ {
+ log<level::ERR>("Temperature readings JSON file not found");
+ elog<InternalFailure>();
+ }
+
+ auto data = Json::parse(jsonFile, nullptr, false);
+ if (data.is_discarded())
+ {
+ log<level::ERR>("Temperature readings JSON parser failure");
+ elog<InternalFailure>();
+ }
+
+ return data;
+}
+
} // namespace dcmi
ipmi_ret_t getPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
@@ -742,25 +773,6 @@ namespace dcmi
namespace temp_readings
{
-Json parseConfig()
-{
- std::ifstream jsonFile(configFile);
- if (!jsonFile.is_open())
- {
- log<level::ERR>("Temperature readings JSON file not found");
- elog<InternalFailure>();
- }
-
- auto data = Json::parse(jsonFile, nullptr, false);
- if (data.is_discarded())
- {
- log<level::ERR>("Temperature readings JSON parser failure");
- elog<InternalFailure>();
- }
-
- return data;
-}
-
Temperature readTemp(const std::string& dbusService,
const std::string& dbusPath)
{
@@ -815,7 +827,7 @@ std::tuple<Response, NumInstances> read(const std::string& type,
elog<InternalFailure>();
}
- auto data = parseConfig();
+ auto data = parseSensorConfig();
static const std::vector<Json> empty{};
std::vector<Json> readings = data.value(type, empty);
size_t numInstances = readings.size();
@@ -868,7 +880,7 @@ std::tuple<ResponseList, NumInstances> readAll(const std::string& type,
sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
size_t numInstances = 0;
- auto data = parseConfig();
+ auto data = parseSensorConfig();
static const std::vector<Json> empty{};
std::vector<Json> readings = data.value(type, empty);
numInstances = readings.size();
@@ -925,17 +937,6 @@ ipmi_ret_t getTempReadings(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
ipmi_request_t request, ipmi_response_t response,
ipmi_data_len_t data_len, ipmi_context_t context)
{
- // Refer Table 6-14, DCMI Entity ID Extension, DCMI v1.5 spec
- static const std::map<uint8_t, std::string> entityIdToName
- {
- {0x40, "inlet"},
- {0x37, "inlet"},
- {0x41, "cpu"},
- {0x03, "cpu"},
- {0x42, "baseboard"},
- {0x07, "baseboard"}
- };
-
auto requestData =
reinterpret_cast<const dcmi::GetTempReadingsRequest*>(request);
auto responseData =
@@ -949,8 +950,8 @@ ipmi_ret_t getTempReadings(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
}
*data_len = 0;
- auto it = entityIdToName.find(requestData->entityId);
- if (it == entityIdToName.end())
+ auto it = dcmi::entityIdToName.find(requestData->entityId);
+ if (it == dcmi::entityIdToName.end())
{
log<level::ERR>("Unknown Entity ID",
entry("ENTITY_ID=%d", requestData->entityId));
@@ -1107,6 +1108,118 @@ ipmi_ret_t getPowerReading(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
return rc;
}
+namespace dcmi
+{
+namespace sensor_info
+{
+
+std::tuple<Response, NumInstances> read(const std::string& type,
+ uint8_t instance,
+ const Json& config)
+{
+ Response empty{};
+ return std::make_tuple(empty, 0);
+}
+
+std::tuple<ResponseList, NumInstances> readAll(const std::string& type,
+ uint8_t instanceStart,
+ const Json& config)
+{
+ ResponseList empty{};
+ return std::make_tuple(empty, 0);
+}
+
+} // namespace sensor_info
+} // namespace dcmi
+
+ipmi_ret_t getSensorInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ auto requestData =
+ reinterpret_cast<const dcmi::GetSensorInfoRequest*>(request);
+ auto responseData =
+ reinterpret_cast<dcmi::GetSensorInfoResponseHdr*>(response);
+
+ if (*data_len != sizeof(dcmi::GetSensorInfoRequest))
+ {
+ log<level::ERR>("Malformed request data",
+ entry("DATA_SIZE=%d", *data_len));
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+ }
+ *data_len = 0;
+
+ auto it = dcmi::entityIdToName.find(requestData->entityId);
+ if (it == dcmi::entityIdToName.end())
+ {
+ log<level::ERR>("Unknown Entity ID",
+ entry("ENTITY_ID=%d", requestData->entityId));
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ if (requestData->groupID != dcmi::groupExtId)
+ {
+ log<level::ERR>("Invalid Group ID",
+ entry("GROUP_ID=%d", requestData->groupID));
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ if (requestData->sensorType != dcmi::temperatureSensorType)
+ {
+ log<level::ERR>("Invalid sensor type",
+ entry("SENSOR_TYPE=%d", requestData->sensorType));
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ dcmi::sensor_info::ResponseList sensors{};
+ static dcmi::Json config{};
+ static bool parsed = false;
+
+ try
+ {
+ if (!parsed)
+ {
+ config = dcmi::parseSensorConfig();
+ parsed = true;
+ }
+
+ if (!requestData->entityInstance)
+ {
+ // Read all instances
+ std::tie(sensors, responseData->numInstances) =
+ dcmi::sensor_info::readAll(it->second,
+ requestData->instanceStart,
+ config);
+ }
+ else
+ {
+ // Read one instance
+ sensors.resize(1);
+ std::tie(sensors[0], responseData->numInstances) =
+ dcmi::sensor_info::read(it->second,
+ requestData->entityInstance,
+ config);
+ }
+ responseData->numRecords = sensors.size();
+ }
+ catch (InternalFailure& e)
+ {
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+
+ responseData->groupID = dcmi::groupExtId;
+ size_t payloadSize = sensors.size() * sizeof(dcmi::sensor_info::Response);
+ if (!sensors.empty())
+ {
+ memcpy(responseData + 1, // copy payload right after the response header
+ sensors.data(),
+ payloadSize);
+ }
+ *data_len = sizeof(dcmi::GetSensorInfoResponseHdr) + payloadSize;
+
+ return IPMI_CC_OK;
+}
+
void register_netfn_dcmi_functions()
{
// <Get Power Limit>
@@ -1168,6 +1281,11 @@ void register_netfn_dcmi_functions()
// <Get Power Reading>
ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_POWER_READING,
NULL, getPowerReading, PRIVILEGE_USER);
+
+ // <Get Sensor Info>
+ ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_SENSOR_INFO,
+ NULL, getSensorInfo, PRIVILEGE_USER);
+
return;
}
// 956379
diff --git a/dcmihandler.hpp b/dcmihandler.hpp
index 4e95eba..09921a0 100644
--- a/dcmihandler.hpp
+++ b/dcmihandler.hpp
@@ -10,6 +10,9 @@
namespace dcmi
{
+using NumInstances = size_t;
+using Json = nlohmann::json;
+
enum Commands
{
// Get capability bits
@@ -19,6 +22,7 @@ enum Commands
SET_POWER_LIMIT = 0x04,
APPLY_POWER_LIMIT = 0x05,
GET_ASSET_TAG = 0x06,
+ GET_SENSOR_INFO = 0x07,
SET_ASSET_TAG = 0x08,
GET_MGMNT_CTRL_ID_STR = 0x09,
SET_MGMNT_CTRL_ID_STR = 0x0A,
@@ -36,6 +40,9 @@ static constexpr auto networkConfigIntf =
"xyz.openbmc_project.Network.SystemConfiguration";
static constexpr auto hostNameProp = "HostName";
static constexpr auto temperatureSensorType = 0x01;
+static constexpr auto maxInstances = 255;
+static constexpr auto configFile =
+ "/usr/share/ipmi-providers/dcmi_sensors.json";
namespace assettag
{
@@ -50,10 +57,7 @@ namespace assettag
namespace temp_readings
{
static constexpr auto maxDataSets = 8;
- static constexpr auto maxInstances = 255;
static constexpr auto maxTemp = 127; // degrees C
- static constexpr auto configFile =
- "/usr/share/ipmi-providers/dcmi_temp_readings.json";
/** @struct Response
*
@@ -73,13 +77,28 @@ namespace temp_readings
} __attribute__((packed));
using ResponseList = std::vector<Response>;
- using NumInstances = size_t;
using Value = uint8_t;
using Sign = bool;
using Temperature = std::tuple<Value, Sign>;
- using Json = nlohmann::json;
}
+namespace sensor_info
+{
+ static constexpr auto maxRecords = 8;
+
+ /** @struct Response
+ *
+ * DCMI payload for Get Sensor Info response
+ */
+ struct Response
+ {
+ uint8_t recordIdLsb; //!< SDR record id LS byte
+ uint8_t recordIdMsb; //!< SDR record id MS byte
+ } __attribute__((packed));
+
+ using ResponseList = std::vector<Response>;
+} // namespace sensor_info
+
static constexpr auto groupExtId = 0xDC;
static constexpr auto assetTagMaxOffset = 62;
@@ -381,6 +400,13 @@ struct GetTempReadingsResponseHdr
uint8_t numDataSets; //!< No. of sets of temperature data
} __attribute__((packed));
+/** @brief Parse out JSON config file containing information
+ * related to sensors.
+ *
+ * @return A json object
+ */
+Json parseSensorConfig();
+
namespace temp_readings
{
/** @brief Read temperature from a d-bus object, scale it as per dcmi
@@ -394,13 +420,6 @@ namespace temp_readings
Temperature readTemp(const std::string& dbusService,
const std::string& dbusPath);
- /** @brief Parse out JSON config file containing information
- * related to temperature readings.
- *
- * @return A json object
- */
- Json parseConfig();
-
/** @brief Read temperatures and fill up DCMI response for the Get
* Temperature Readings command. This looks at a specific
* instance.
@@ -428,6 +447,39 @@ namespace temp_readings
uint8_t instanceStart);
}
+namespace sensor_info
+{
+ /** @brief Read sensor info and fill up DCMI response for the Get
+ * Sensor Info command. This looks at a specific
+ * instance.
+ *
+ * @param[in] type - one of "inlet", "cpu", "baseboard"
+ * @param[in] instance - A non-zero Entity instance number
+ * @param[in] config - JSON config info about DCMI sensors
+ *
+ * @return A tuple, containing a sensor info response and
+ * number of instances.
+ */
+ std::tuple<Response, NumInstances> read(const std::string& type,
+ uint8_t instance,
+ const Json& config);
+
+ /** @brief Read sensor info and fill up DCMI response for the Get
+ * Sensor Info command. This looks at a range of
+ * instances.
+ *
+ * @param[in] type - one of "inlet", "cpu", "baseboard"
+ * @param[in] instanceStart - Entity instance start index
+ * @param[in] config - JSON config info about DCMI sensors
+ *
+ * @return A tuple, containing a list of sensor info responses and the
+ * number of instances.
+ */
+ std::tuple<ResponseList, NumInstances> readAll(const std::string& type,
+ uint8_t instanceStart,
+ const Json& config);
+} // namespace sensor_info
+
/** @brief Read power reading from power reading sensor object
*
* @param[in] bus - dbus connection
@@ -469,6 +521,30 @@ struct GetPowerReadingResponse
uint8_t powerReadingState; //!< Power Reading State
} __attribute__((packed));
+/** @struct GetSensorInfoRequest
+ *
+ * DCMI payload for Get Sensor Info request
+ */
+struct GetSensorInfoRequest
+{
+ uint8_t groupID; //!< Group extension identification.
+ uint8_t sensorType; //!< Type of the sensor
+ uint8_t entityId; //!< Entity ID
+ uint8_t entityInstance; //!< Entity Instance (0 means all instances)
+ uint8_t instanceStart; //!< Instance start (used if instance is 0)
+} __attribute__((packed));
+
+/** @struct GetSensorInfoResponseHdr
+ *
+ * DCMI header for Get Sensor Info response
+ */
+struct GetSensorInfoResponseHdr
+{
+ uint8_t groupID; //!< Group extension identification.
+ uint8_t numInstances; //!< No. of instances for requested id
+ uint8_t numRecords; //!< No. of record ids in the response
+} __attribute__((packed));
+
} // namespace dcmi
#endif
diff --git a/host-ipmid-whitelist.conf b/host-ipmid-whitelist.conf
index 0c9c382..97544a0 100644
--- a/host-ipmid-whitelist.conf
+++ b/host-ipmid-whitelist.conf
@@ -31,4 +31,5 @@
0x2C:0x02 //<Group Extension>:<Get Power Reading>
0x2C:0x03 //<Group Extension>:<Get Power Limit>
0x2C:0x06 //<Group Extension>:<Get Asset Tag>
+0x2C:0x07 //<Group Extension>:<Get Sensor Info>
0x2C:0x10 //<Group Extension>:<Get Temperature Readings>
OpenPOWER on IntegriCloud