From bbef71c2a9aab57a826b4c7ec8f183e92eb6e28c Mon Sep 17 00:00:00 2001 From: Emily Shaffer Date: Mon, 8 May 2017 16:36:17 -0700 Subject: sensorhandler: implement get SDR Change-Id: I79dc59585c1f3008fc42e95a5a4792afd7268255 Signed-off-by: Emily Shaffer Signed-off-by: Patrick Williams --- sensorhandler.cpp | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 157 insertions(+), 2 deletions(-) (limited to 'sensorhandler.cpp') diff --git a/sensorhandler.cpp b/sensorhandler.cpp index da6cfd9..cbf6b65 100644 --- a/sensorhandler.cpp +++ b/sensorhandler.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "host-ipmid/ipmid-api.h" #include @@ -632,8 +633,8 @@ ipmi_ret_t ipmi_sen_get_sensor_reading(ipmi_netfn_t netfn, ipmi_cmd_t cmd, } resp->value = raw_value * pow(10,scale); - resp->operation = 0; - resp->indication[0] = 0; + resp->operation = 1<<6; // scanning enabled + resp->indication[0] = 0; // not a threshold sensor. ignore resp->indication[1] = 0; rc = IPMI_CC_OK; *data_len=sizeof(sensorreadingresp_t); @@ -708,6 +709,152 @@ ipmi_ret_t ipmi_sen_reserve_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, return IPMI_CC_OK; } +ipmi_ret_t populate_record_from_dbus(get_sdr::SensorDataFullRecordBody *body, + const ipmi::sensor::Info *info, + ipmi_data_len_t data_len) +{ + /* Functional sensor case */ + if (info->sensorInterfaces.begin()->first == + "xyz.openbmc_project.Sensor.Value") + { + // Get bus + sd_bus *bus = ipmid_get_sd_bus_connection(); + dbus_interface_t iface; + + if (0 > find_openbmc_path(body->entity_id, &iface)) + return IPMI_CC_SENSOR_INVALID; + + body->sensor_units_1 = 0; // unsigned, no rate, no modifier, not a % + + /* Unit info */ + char *raw_cstr; + if (0 > sd_bus_get_property_string(bus, iface.bus, iface.path, + iface.interface, "Unit", NULL, + &raw_cstr)) { + fprintf(stderr, "Expected to find Unit interface in bus %s, path %s, but it was missing.\n", + iface.bus, iface.path); + return IPMI_CC_SENSOR_INVALID; + } + + std::string raw_str(raw_cstr); + namespace server = sdbusplus::xyz::openbmc_project::Sensor::server; + server::Value::Unit unit = + server::Value::convertUnitFromString(raw_str); + + // Unit strings defined in + // phosphor-dbus-interfaces/xyz/openbmc_project/Sensor/Value.interface.yaml + switch (unit) + { + case server::Value::Unit::DegreesC: + body->sensor_units_2_base = get_sdr::SENSOR_UNIT_DEGREES_C; + break; + case server::Value::Unit::RPMS: + body->sensor_units_2_base = get_sdr::SENSOR_UNIT_REVOLUTIONS; // revolutions + get_sdr::body::set_rate_unit(0b100, body); // per minute + break; + case server::Value::Unit::Volts: + body->sensor_units_2_base = get_sdr::SENSOR_UNIT_VOLTS; + break; + case server::Value::Unit::Meters: + body->sensor_units_2_base = get_sdr::SENSOR_UNIT_METERS; + break; + case server::Value::Unit::Amperes: + body->sensor_units_2_base = get_sdr::SENSOR_UNIT_AMPERES; + break; + case server::Value::Unit::Joules: + body->sensor_units_2_base = get_sdr::SENSOR_UNIT_JOULES; + break; + default: + fprintf(stderr, "Unknown value unit type: = %s\n", raw_cstr); + } + + free(raw_cstr); + + /* Modifiers to reading info */ + get_sdr::body::set_b(0, body); + get_sdr::body::set_m(1, body); + body->r_b_exponents = 0; + + /* ID string */ + std::string id_string = info->sensorPath.substr( + info->sensorPath.find_last_of('/')+1, info->sensorPath.length()); + get_sdr::body::set_id_type(0b00, body); // 00 = unicode + if (id_string.length() > FULL_RECORD_ID_STR_MAX_LENGTH) + { + get_sdr::body::set_id_strlen(FULL_RECORD_ID_STR_MAX_LENGTH, body); + } + else + { + get_sdr::body::set_id_strlen(id_string.length(), body); + } + strncpy(body->id_string, id_string.c_str(), + get_sdr::body::get_id_strlen(body)); + } + + 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) +{ + ipmi_ret_t ret = IPMI_CC_OK; + get_sdr::GetSdrReq *req = (get_sdr::GetSdrReq*)request; + get_sdr::GetSdrResp *resp = (get_sdr::GetSdrResp*)response; + get_sdr::SensorDataFullRecord record = {0}; + if (req != NULL) + { + // Note: we use an iterator so we can provide the next ID at the end of + // the call. + auto sensor = sensors.begin(); + + // At the beginning of a scan, the host side will send us id=0. + if (get_sdr::request::get_record_id(req) != 0) + { + sensor = sensors.find(get_sdr::request::get_record_id(req)); + if(sensor == sensors.end()) { + return IPMI_CC_SENSOR_INVALID; + } + } + + uint8_t sensor_id = sensor->first; + + /* Header */ + get_sdr::header::set_record_id(sensor_id, &(record.header)); + record.header.sdr_version = 0x51; // Based on IPMI Spec v2.0 rev 1.1 + record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD; + record.header.record_length = sizeof(get_sdr::SensorDataFullRecord); + + /* Key */ + record.key.sensor_number = sensor_id; + + /* Body */ + record.body.entity_id = sensor_id; + record.body.sensor_type = sensor->second.sensorType; + record.body.event_reading_type = sensor->second.sensorReadingType; + + // Set the type-specific details given the DBus interface + ret = populate_record_from_dbus(&(record.body), &(sensor->second), + data_len); + + if (++sensor == sensors.end()) + { + get_sdr::response::set_next_record_id(0xFFFF, resp); // last record + } + else + { + get_sdr::response::set_next_record_id(sensor->first, resp); + } + + *data_len = sizeof(get_sdr::GetSdrResp) - req->offset; + memcpy(resp->record_data, (char*)&record + req->offset, + sizeof(get_sdr::SensorDataFullRecord) - req->offset); + } + + return ret; +} + + void register_netfn_sen_functions() { // @@ -751,5 +898,13 @@ void register_netfn_sen_functions() ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SDR_INFO, nullptr, ipmi_sen_get_sdr_info, PRIVILEGE_USER); + + // + printf("Registering NetFn:[0x%X], Cmd:[0x%x]\n", + NETFUN_SENSOR, IPMI_CMD_GET_SDR); + ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SDR, + nullptr, ipmi_sen_get_sdr, + PRIVILEGE_USER); + return; } -- cgit v1.2.1