summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipmid.cpp11
-rw-r--r--sensorhandler.cpp129
-rw-r--r--sensorhandler.h75
3 files changed, 201 insertions, 14 deletions
diff --git a/ipmid.cpp b/ipmid.cpp
index f06adc5..a05992b 100644
--- a/ipmid.cpp
+++ b/ipmid.cpp
@@ -380,10 +380,11 @@ static int handle_ipmi_command(sd_bus_message *m, void *user_data, sd_bus_error
if(r != 0)
{
fprintf(stderr,"ERROR:[0x%X] handling NetFn:[0x%X], Cmd:[0x%X]\n",r, netfn, cmd);
-
- if(r < 0) {
- response[0] = IPMI_CC_UNSPECIFIED_ERROR;
- }
+ resplen = 0;
+ }
+ else
+ {
+ resplen = resplen - 1; // first byte is for return code.
}
fprintf(ipmiio, "IPMI Response:\n");
@@ -391,7 +392,7 @@ static int handle_ipmi_command(sd_bus_message *m, void *user_data, sd_bus_error
// Send the response buffer from the ipmi command
r = send_ipmi_message(m, sequence, netfn, lun, cmd, response[0],
- ((unsigned char *)response) + 1, resplen - 1);
+ ((unsigned char *)response) + 1, resplen);
if (r < 0) {
fprintf(stderr, "Failed to send the response message\n");
return -1;
diff --git a/sensorhandler.cpp b/sensorhandler.cpp
index 036eb22..1bd10b7 100644
--- a/sensorhandler.cpp
+++ b/sensorhandler.cpp
@@ -9,15 +9,23 @@
#include "host-ipmid/ipmid-api.h"
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog-errors.hpp>
+#include "fruread.hpp"
#include "ipmid.hpp"
#include "sensorhandler.h"
#include "types.hpp"
#include "utils.hpp"
#include "xyz/openbmc_project/Common/error.hpp"
+static constexpr uint8_t fruInventoryDevice = 0x10;
+static constexpr uint8_t IPMIFruInventory = 0x02;
+static constexpr uint8_t BMCSlaveAddress = 0x20;
+
extern int updateSensorRecordFromSSRAESC(const void *);
extern sd_bus *bus;
extern const ipmi::sensor::IdInfoMap sensors;
+extern const FruMap frus;
+
+
using namespace phosphor::logging;
using InternalFailure =
sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
@@ -825,7 +833,7 @@ ipmi_ret_t ipmi_sen_get_sdr_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
get_sdr_info::request::get_count(request) == false)
{
// Get Sensor Count
- resp->count = sensors.size();
+ resp->count = sensors.size() + frus.size();
}
else
{
@@ -1009,6 +1017,97 @@ ipmi_ret_t populate_record_from_dbus(get_sdr::SensorDataFullRecordBody *body,
return IPMI_CC_OK;
};
+ipmi_ret_t ipmi_fru_get_sdr(ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len)
+{
+ auto req = reinterpret_cast<get_sdr::GetSdrReq*>(request);
+ auto resp = reinterpret_cast<get_sdr::GetSdrResp*>(response);
+ get_sdr::SensorDataFruRecord record {};
+ auto dataLength = 0;
+
+ auto fru = frus.begin();
+ uint8_t fruID {};
+ auto recordID = get_sdr::request::get_record_id(req);
+
+ fruID = recordID - FRU_RECORD_ID_START;
+ fru = frus.find(fruID);
+ if (fru == frus.end())
+ {
+ return IPMI_CC_SENSOR_INVALID;
+ }
+
+ /* Header */
+ get_sdr::header::set_record_id(recordID, &(record.header));
+ record.header.sdr_version = SDR_VERSION; // Based on IPMI Spec v2.0 rev 1.1
+ record.header.record_type = get_sdr::SENSOR_DATA_FRU_RECORD;
+ record.header.record_length = sizeof(record.key) + sizeof(record.body);
+
+ /* Key */
+ record.key.fruID = fruID;
+ record.key.accessLun |= IPMI_LOGICAL_FRU;
+ record.key.deviceAddress = BMCSlaveAddress;
+
+ /* Body */
+ record.body.entityID = fru->second[0].entityID;
+ record.body.entityInstance = fru->second[0].entityInstance;
+ record.body.deviceType = fruInventoryDevice;
+ record.body.deviceTypeModifier = IPMIFruInventory;
+
+ /* Device ID string */
+ auto deviceID = fru->second[0].path.substr(
+ fru->second[0].path.find_last_of('/') + 1,
+ fru->second[0].path.length());
+
+
+ if (deviceID.length() > get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH)
+ {
+ get_sdr::body::set_device_id_strlen(
+ get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH,
+ &(record.body));
+ }
+ else
+ {
+ get_sdr::body::set_device_id_strlen(deviceID.length(),
+ &(record.body));
+ }
+
+ strncpy(record.body.deviceID, deviceID.c_str(),
+ get_sdr::body::get_device_id_strlen(&(record.body)));
+
+ if (++fru == frus.end())
+ {
+ get_sdr::response::set_next_record_id(END_OF_RECORD, resp); // last record
+ }
+ else
+ {
+ get_sdr::response::set_next_record_id(
+ (FRU_RECORD_ID_START + fru->first), resp);
+ }
+
+ if (req->bytes_to_read > (sizeof(*resp) - req->offset))
+ {
+ dataLength = (sizeof(*resp) - req->offset);
+ }
+ else
+ {
+ dataLength = req->bytes_to_read;
+ }
+
+ if (dataLength <= 0)
+ {
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+ }
+
+ memcpy(resp->record_data,
+ reinterpret_cast<uint8_t*>(&record) + req->offset,
+ (dataLength));
+
+ *data_len = dataLength;
+ *data_len += 2; // additional 2 bytes for next record ID
+
+ return IPMI_CC_OK;
+}
+
ipmi_ret_t ipmi_sen_get_sdr(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)
@@ -1022,13 +1121,25 @@ ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
// Note: we use an iterator so we can provide the next ID at the end of
// the call.
auto sensor = sensors.begin();
+ auto recordID = get_sdr::request::get_record_id(req);
// At the beginning of a scan, the host side will send us id=0.
- if (get_sdr::request::get_record_id(req) != 0)
+ if (recordID != 0)
{
- sensor = sensors.find(get_sdr::request::get_record_id(req));
- if(sensor == sensors.end()) {
- return IPMI_CC_SENSOR_INVALID;
+ // recordID greater then 255,it means it is a FRU record.
+ // Currently we are supporting two record types either FULL record
+ // or FRU record.
+ if (recordID >= FRU_RECORD_ID_START)
+ {
+ return ipmi_fru_get_sdr(request, response, data_len);
+ }
+ else
+ {
+ sensor = sensors.find(recordID);
+ if (sensor == sensors.end())
+ {
+ return IPMI_CC_SENSOR_INVALID;
+ }
}
}
@@ -1056,7 +1167,13 @@ ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
if (++sensor == sensors.end())
{
- get_sdr::response::set_next_record_id(0xFFFF, resp); // last record
+ // we have reached till end of sensor, so assign the next record id
+ // to 256(Max Sensor ID = 255) + FRU ID(may start with 0).
+ auto next_record_id = (frus.size()) ?
+ frus.begin()->first + FRU_RECORD_ID_START :
+ END_OF_RECORD;
+
+ get_sdr::response::set_next_record_id(next_record_id, resp);
}
else
{
diff --git a/sensorhandler.h b/sensorhandler.h
index 1cf43ca..e32405d 100644
--- a/sensorhandler.h
+++ b/sensorhandler.h
@@ -16,6 +16,16 @@ enum ipmi_netfn_sen_cmds
IPMI_CMD_GET_SENSOR_THRESHOLDS = 0x27,
};
+/**
+ * @enum device_type
+ * IPMI FRU device types
+ */
+enum device_type
+{
+ IPMI_PHYSICAL_FRU = 0x00,
+ IPMI_LOGICAL_FRU = 0x80,
+};
+
// Discrete sensor types.
enum ipmi_sensor_types
{
@@ -40,6 +50,11 @@ int set_sensor_dbus_state_s(uint8_t , const char *, const char *);
int set_sensor_dbus_state_y(uint8_t , const char *, const uint8_t);
int find_openbmc_path(uint8_t , dbus_interface_t *);
+static const uint16_t FRU_RECORD_ID_START = 256;
+static const uint8_t SDR_VERSION = 0x51;
+static const uint16_t END_OF_RECORD = 0xFFFF;
+static const uint8_t LENGTH_MASK = 0x1F;
+
/**
* Get SDR Info
*/
@@ -109,7 +124,7 @@ inline uint8_t get_reservation_id(GetSdrReq* req)
return (req->reservation_id_lsb + (req->reservation_id_msb << 8));
};
-inline uint8_t get_record_id(GetSdrReq* req)
+inline uint16_t get_record_id(GetSdrReq* req)
{
return (req->record_id_lsb + (req->record_id_msb << 8));
};
@@ -127,7 +142,7 @@ struct GetSdrResp
namespace response
{
-inline void set_next_record_id(int next, GetSdrResp* resp)
+inline void set_next_record_id(uint16_t next, GetSdrResp* resp)
{
resp->next_record_id_lsb = next & 0xff;
resp->next_record_id_msb = (next >> 8) & 0xff;
@@ -158,7 +173,8 @@ inline void set_record_id(int id, SensorDataRecordHeader* hdr)
enum SensorDataRecordType
{
- SENSOR_DATA_FULL_RECORD = 1,
+ SENSOR_DATA_FULL_RECORD = 0x1,
+ SENSOR_DATA_FRU_RECORD = 0x11,
};
// Record key
@@ -169,6 +185,18 @@ struct SensorDataRecordKey
uint8_t sensor_number;
} __attribute__((packed));
+/** @struct SensorDataFruRecordKey
+ *
+ * FRU Device Locator Record(key) - SDR Type 11
+ */
+struct SensorDataFruRecordKey
+{
+ uint8_t deviceAddress;
+ uint8_t fruID;
+ uint8_t accessLun;
+ uint8_t channelNumber;
+} __attribute__((packed));
+
namespace key
{
@@ -219,6 +247,9 @@ struct GetSensorThresholdsResponse
// Body - full record
#define FULL_RECORD_ID_STR_MAX_LENGTH 16
+
+static const int FRU_RECORD_DEVICE_ID_MAX_LENGTH = 16;
+
struct SensorDataFullRecordBody
{
uint8_t entity_id;
@@ -260,6 +291,22 @@ struct SensorDataFullRecordBody
char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
} __attribute__((packed));
+/** @struct SensorDataFruRecordBody
+ *
+ * FRU Device Locator Record(body) - SDR Type 11
+ */
+struct SensorDataFruRecordBody
+{
+ uint8_t reserved;
+ uint8_t deviceType;
+ uint8_t deviceTypeModifier;
+ uint8_t entityID;
+ uint8_t entityInstance;
+ uint8_t oem;
+ uint8_t deviceIDLen;
+ char deviceID[FRU_RECORD_DEVICE_ID_MAX_LENGTH];
+} __attribute__((packed));
+
namespace body
{
@@ -464,6 +511,17 @@ inline void set_id_type(uint8_t type, SensorDataFullRecordBody* body)
body->id_string_info |= (type & 0x3)<<6;
};
+inline void set_device_id_strlen(uint8_t len, SensorDataFruRecordBody* body)
+{
+ body->deviceIDLen &= ~(LENGTH_MASK);
+ body->deviceIDLen |= len & LENGTH_MASK;
+};
+
+inline uint8_t get_device_id_strlen(SensorDataFruRecordBody* body)
+{
+ return body->deviceIDLen & LENGTH_MASK;
+};
+
} // namespace body
// More types contained in section 43.17 Sensor Unit Type Codes,
@@ -486,6 +544,17 @@ struct SensorDataFullRecord
SensorDataFullRecordBody body;
} __attribute__((packed));
+/** @struct SensorDataFruRecord
+ *
+ * FRU Device Locator Record - SDR Type 11
+ */
+struct SensorDataFruRecord
+{
+ SensorDataRecordHeader header;
+ SensorDataFruRecordKey key;
+ SensorDataFruRecordBody body;
+} __attribute__((packed));
+
} // get_sdr
namespace ipmi
OpenPOWER on IntegriCloud