1d700e76aSTom #include <mapper.h> 21fabf229SEmily Shaffer #include <math.h> 398a23840SMatthew Barth #include <stdio.h> 498a23840SMatthew Barth #include <string.h> 5cc941e15SEmily Shaffer #include <set> 6be703f71STom Joseph #include <bitset> 7bbef71c2SEmily Shaffer #include <xyz/openbmc_project/Sensor/Value/server.hpp> 898a23840SMatthew Barth #include <systemd/sd-bus.h> 9be703f71STom Joseph #include "host-ipmid/ipmid-api.h" 10be703f71STom Joseph #include <phosphor-logging/log.hpp> 1118e99992SDhruvaraj Subhashchandran #include <phosphor-logging/elog-errors.hpp> 12e0cc8553SRatan Gupta #include "fruread.hpp" 13d700e76aSTom #include "ipmid.hpp" 14be703f71STom Joseph #include "sensorhandler.h" 15be703f71STom Joseph #include "types.hpp" 16be703f71STom Joseph #include "utils.hpp" 1718e99992SDhruvaraj Subhashchandran #include "xyz/openbmc_project/Common/error.hpp" 1818e99992SDhruvaraj Subhashchandran 19e0cc8553SRatan Gupta static constexpr uint8_t fruInventoryDevice = 0x10; 20e0cc8553SRatan Gupta static constexpr uint8_t IPMIFruInventory = 0x02; 21e0cc8553SRatan Gupta static constexpr uint8_t BMCSlaveAddress = 0x20; 22e0cc8553SRatan Gupta 2398a23840SMatthew Barth extern int updateSensorRecordFromSSRAESC(const void *); 24d700e76aSTom extern sd_bus *bus; 25be703f71STom Joseph extern const ipmi::sensor::IdInfoMap sensors; 26e0cc8553SRatan Gupta extern const FruMap frus; 27e0cc8553SRatan Gupta 28e0cc8553SRatan Gupta 29be703f71STom Joseph using namespace phosphor::logging; 3018e99992SDhruvaraj Subhashchandran using InternalFailure = 3118e99992SDhruvaraj Subhashchandran sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 3298a23840SMatthew Barth 3398a23840SMatthew Barth void register_netfn_sen_functions() __attribute__((constructor)); 3498a23840SMatthew Barth 3598a23840SMatthew Barth struct sensorTypemap_t { 3698a23840SMatthew Barth uint8_t number; 3798a23840SMatthew Barth uint8_t typecode; 3898a23840SMatthew Barth char dbusname[32]; 3998a23840SMatthew Barth } ; 4098a23840SMatthew Barth 4198a23840SMatthew Barth sensorTypemap_t g_SensorTypeMap[] = { 4298a23840SMatthew Barth 4398a23840SMatthew Barth {0x01, 0x6F, "Temp"}, 4498a23840SMatthew Barth {0x0C, 0x6F, "DIMM"}, 4598a23840SMatthew Barth {0x0C, 0x6F, "MEMORY_BUFFER"}, 4698a23840SMatthew Barth {0x07, 0x6F, "PROC"}, 4798a23840SMatthew Barth {0x07, 0x6F, "CORE"}, 4898a23840SMatthew Barth {0x07, 0x6F, "CPU"}, 4998a23840SMatthew Barth {0x0F, 0x6F, "BootProgress"}, 5098a23840SMatthew Barth {0xe9, 0x09, "OccStatus"}, // E9 is an internal mapping to handle sensor type code os 0x09 5198a23840SMatthew Barth {0xC3, 0x6F, "BootCount"}, 5298a23840SMatthew Barth {0x1F, 0x6F, "OperatingSystemStatus"}, 5398a23840SMatthew Barth {0x12, 0x6F, "SYSTEM_EVENT"}, 5498a23840SMatthew Barth {0xC7, 0x03, "SYSTEM"}, 5598a23840SMatthew Barth {0xC7, 0x03, "MAIN_PLANAR"}, 5698a23840SMatthew Barth {0xC2, 0x6F, "PowerCap"}, 57558184eaSTom Joseph {0x0b, 0xCA, "PowerSupplyRedundancy"}, 580661beb1SJayanth Othayoth {0xDA, 0x03, "TurboAllowed"}, 59558184eaSTom Joseph {0xD8, 0xC8, "PowerSupplyDerating"}, 6098a23840SMatthew Barth {0xFF, 0x00, ""}, 6198a23840SMatthew Barth }; 6298a23840SMatthew Barth 6398a23840SMatthew Barth 6498a23840SMatthew Barth struct sensor_data_t { 6598a23840SMatthew Barth uint8_t sennum; 6698a23840SMatthew Barth } __attribute__ ((packed)) ; 6798a23840SMatthew Barth 6898a23840SMatthew Barth struct sensorreadingresp_t { 6998a23840SMatthew Barth uint8_t value; 7098a23840SMatthew Barth uint8_t operation; 7198a23840SMatthew Barth uint8_t indication[2]; 7298a23840SMatthew Barth } __attribute__ ((packed)) ; 7398a23840SMatthew Barth 742ae09b9aSEmily Shaffer int get_bus_for_path(const char *path, char **busname) { 752ae09b9aSEmily Shaffer return mapper_get_service(bus, path, busname); 762ae09b9aSEmily Shaffer } 77d700e76aSTom 782ae09b9aSEmily Shaffer int legacy_dbus_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) { 79d700e76aSTom char *busname = NULL; 80d700e76aSTom const char *iface = "org.openbmc.managers.System"; 81d700e76aSTom const char *objname = "/org/openbmc/managers/System"; 82d700e76aSTom char *str1 = NULL, *str2, *str3; 83d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 84d700e76aSTom sd_bus_message *reply = NULL; 85d700e76aSTom 86d700e76aSTom 87d700e76aSTom int r; 882ae09b9aSEmily Shaffer r = get_bus_for_path(objname, &busname); 89d700e76aSTom if (r < 0) { 90819ddd42SBrad Bishop fprintf(stderr, "Failed to get %s busname: %s\n", 91819ddd42SBrad Bishop objname, strerror(-r)); 92d700e76aSTom goto final; 93d700e76aSTom } 94d700e76aSTom 95d700e76aSTom r = sd_bus_call_method(bus,busname,objname,iface, "getObjectFromByteId", 96d700e76aSTom &error, &reply, "sy", type, num); 97d700e76aSTom if (r < 0) { 98d700e76aSTom fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); 99d700e76aSTom goto final; 100d700e76aSTom } 101d700e76aSTom 102d700e76aSTom r = sd_bus_message_read(reply, "(ss)", &str2, &str3); 103d700e76aSTom if (r < 0) { 104d700e76aSTom fprintf(stderr, "Failed to get a response: %s", strerror(-r)); 105d700e76aSTom goto final; 106d700e76aSTom } 107d700e76aSTom 10891875f77SLei YU if (strlen(str2) == 0) 10991875f77SLei YU { 11091875f77SLei YU // Path being empty occurs when the sensor id is not in SystemManager 11191875f77SLei YU r = -EINVAL; 11291875f77SLei YU goto final; 11391875f77SLei YU } 11491875f77SLei YU 1152ae09b9aSEmily Shaffer r = get_bus_for_path(str2, &str1); 116d700e76aSTom if (r < 0) { 117819ddd42SBrad Bishop fprintf(stderr, "Failed to get %s busname: %s\n", 118819ddd42SBrad Bishop str2, strerror(-r)); 119d700e76aSTom goto final; 120d700e76aSTom } 121d700e76aSTom 122d700e76aSTom strncpy(interface->bus, str1, MAX_DBUS_PATH); 123d700e76aSTom strncpy(interface->path, str2, MAX_DBUS_PATH); 124d700e76aSTom strncpy(interface->interface, str3, MAX_DBUS_PATH); 125d700e76aSTom 126d700e76aSTom interface->sensornumber = num; 1277117441cSEmily Shaffer // Make sure we know that the type hasn't been set, as newer codebase will 1287117441cSEmily Shaffer // set it automatically from the YAML at this step. 1297117441cSEmily Shaffer interface->sensortype = 0; 130d700e76aSTom 131d700e76aSTom final: 132d700e76aSTom 133d700e76aSTom sd_bus_error_free(&error); 134d700e76aSTom reply = sd_bus_message_unref(reply); 135d700e76aSTom free(busname); 136d700e76aSTom free(str1); 137d700e76aSTom 138d700e76aSTom return r; 139d700e76aSTom } 140d700e76aSTom 1412ae09b9aSEmily Shaffer // Use a lookup table to find the interface name of a specific sensor 1422ae09b9aSEmily Shaffer // This will be used until an alternative is found. this is the first 1432ae09b9aSEmily Shaffer // step for mapping IPMI 1442ae09b9aSEmily Shaffer int find_openbmc_path(uint8_t num, dbus_interface_t *interface) { 1452ae09b9aSEmily Shaffer int rc; 1462ae09b9aSEmily Shaffer 1472ae09b9aSEmily Shaffer // When the sensor map does not contain the sensor requested, 1482ae09b9aSEmily Shaffer // fall back to the legacy DBus lookup (deprecated) 1492ae09b9aSEmily Shaffer const auto& sensor_it = sensors.find(num); 1502ae09b9aSEmily Shaffer if (sensor_it == sensors.end()) 1512ae09b9aSEmily Shaffer { 1522ae09b9aSEmily Shaffer return legacy_dbus_openbmc_path("SENSOR", num, interface); 1532ae09b9aSEmily Shaffer } 1542ae09b9aSEmily Shaffer 1552ae09b9aSEmily Shaffer const auto& info = sensor_it->second; 1562ae09b9aSEmily Shaffer 1578451edf5SPatrick Williams char* busname = nullptr; 1582ae09b9aSEmily Shaffer rc = get_bus_for_path(info.sensorPath.c_str(), &busname); 1592ae09b9aSEmily Shaffer if (rc < 0) { 1602ae09b9aSEmily Shaffer fprintf(stderr, "Failed to get %s busname: %s\n", 1612ae09b9aSEmily Shaffer info.sensorPath.c_str(), 1622ae09b9aSEmily Shaffer busname); 1632ae09b9aSEmily Shaffer goto final; 1642ae09b9aSEmily Shaffer } 1652ae09b9aSEmily Shaffer 1662ae09b9aSEmily Shaffer interface->sensortype = info.sensorType; 1672ae09b9aSEmily Shaffer strcpy(interface->bus, busname); 1682ae09b9aSEmily Shaffer strcpy(interface->path, info.sensorPath.c_str()); 1692ae09b9aSEmily Shaffer // Take the interface name from the beginning of the DbusInterfaceMap. This 1702ae09b9aSEmily Shaffer // works for the Value interface but may not suffice for more complex 1712ae09b9aSEmily Shaffer // sensors. 1722ae09b9aSEmily Shaffer // tracked https://github.com/openbmc/phosphor-host-ipmid/issues/103 1731bb0d387SDeepak Kodihalli strcpy(interface->interface, info.propertyInterfaces.begin()->first.c_str()); 1742ae09b9aSEmily Shaffer interface->sensornumber = num; 1752ae09b9aSEmily Shaffer 1762ae09b9aSEmily Shaffer final: 1772ae09b9aSEmily Shaffer free(busname); 1782ae09b9aSEmily Shaffer return rc; 1792ae09b9aSEmily Shaffer } 1802ae09b9aSEmily Shaffer 181d700e76aSTom 182d700e76aSTom ///////////////////////////////////////////////////////////////////// 183d700e76aSTom // 184d700e76aSTom // Routines used by ipmi commands wanting to interact on the dbus 185d700e76aSTom // 186d700e76aSTom ///////////////////////////////////////////////////////////////////// 187d700e76aSTom int set_sensor_dbus_state_s(uint8_t number, const char *method, const char *value) { 188d700e76aSTom 189d700e76aSTom 190d700e76aSTom dbus_interface_t a; 191d700e76aSTom int r; 192d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 193d700e76aSTom sd_bus_message *m=NULL; 194d700e76aSTom 195d700e76aSTom fprintf(ipmidbus, "Attempting to set a dbus Variant Sensor 0x%02x via %s with a value of %s\n", 196d700e76aSTom number, method, value); 197d700e76aSTom 1982ae09b9aSEmily Shaffer r = find_openbmc_path(number, &a); 199d700e76aSTom 200d700e76aSTom if (r < 0) { 201d700e76aSTom fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); 202d700e76aSTom return 0; 203d700e76aSTom } 204d700e76aSTom 205d700e76aSTom r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method); 206d700e76aSTom if (r < 0) { 207d700e76aSTom fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); 208d700e76aSTom goto final; 209d700e76aSTom } 210d700e76aSTom 211d700e76aSTom r = sd_bus_message_append(m, "v", "s", value); 212d700e76aSTom if (r < 0) { 213d700e76aSTom fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r)); 214d700e76aSTom goto final; 215d700e76aSTom } 216d700e76aSTom 217d700e76aSTom 218d700e76aSTom r = sd_bus_call(bus, m, 0, &error, NULL); 219d700e76aSTom if (r < 0) { 220d700e76aSTom fprintf(stderr, "Failed to call the method: %s", strerror(-r)); 221d700e76aSTom } 222d700e76aSTom 223d700e76aSTom final: 224d700e76aSTom sd_bus_error_free(&error); 225d700e76aSTom m = sd_bus_message_unref(m); 226d700e76aSTom 227d700e76aSTom return 0; 228d700e76aSTom } 229d700e76aSTom int set_sensor_dbus_state_y(uint8_t number, const char *method, const uint8_t value) { 230d700e76aSTom 231d700e76aSTom 232d700e76aSTom dbus_interface_t a; 233d700e76aSTom int r; 234d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 235d700e76aSTom sd_bus_message *m=NULL; 236d700e76aSTom 237d700e76aSTom fprintf(ipmidbus, "Attempting to set a dbus Variant Sensor 0x%02x via %s with a value of 0x%02x\n", 238d700e76aSTom number, method, value); 239d700e76aSTom 2402ae09b9aSEmily Shaffer r = find_openbmc_path(number, &a); 241d700e76aSTom 242d700e76aSTom if (r < 0) { 243d700e76aSTom fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); 244d700e76aSTom return 0; 245d700e76aSTom } 246d700e76aSTom 247d700e76aSTom r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method); 248d700e76aSTom if (r < 0) { 249d700e76aSTom fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); 250d700e76aSTom goto final; 251d700e76aSTom } 252d700e76aSTom 253d700e76aSTom r = sd_bus_message_append(m, "v", "i", value); 254d700e76aSTom if (r < 0) { 255d700e76aSTom fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r)); 256d700e76aSTom goto final; 257d700e76aSTom } 258d700e76aSTom 259d700e76aSTom 260d700e76aSTom r = sd_bus_call(bus, m, 0, &error, NULL); 261d700e76aSTom if (r < 0) { 262d700e76aSTom fprintf(stderr, "12 Failed to call the method: %s", strerror(-r)); 263d700e76aSTom } 264d700e76aSTom 265d700e76aSTom final: 266d700e76aSTom sd_bus_error_free(&error); 267d700e76aSTom m = sd_bus_message_unref(m); 268d700e76aSTom 269d700e76aSTom return 0; 270d700e76aSTom } 271d700e76aSTom 27298a23840SMatthew Barth uint8_t dbus_to_sensor_type(char *p) { 27398a23840SMatthew Barth 27498a23840SMatthew Barth sensorTypemap_t *s = g_SensorTypeMap; 27598a23840SMatthew Barth char r=0; 27698a23840SMatthew Barth while (s->number != 0xFF) { 27798a23840SMatthew Barth if (!strcmp(s->dbusname,p)) { 278558184eaSTom Joseph r = s->typecode; 27998a23840SMatthew Barth break; 28098a23840SMatthew Barth } 28198a23840SMatthew Barth s++; 28298a23840SMatthew Barth } 28398a23840SMatthew Barth 28498a23840SMatthew Barth if (s->number == 0xFF) 28598a23840SMatthew Barth printf("Failed to find Sensor Type %s\n", p); 28698a23840SMatthew Barth 28798a23840SMatthew Barth return r; 28898a23840SMatthew Barth } 28998a23840SMatthew Barth 29098a23840SMatthew Barth 291391f3303SEmily Shaffer uint8_t get_type_from_interface(dbus_interface_t dbus_if) { 29298a23840SMatthew Barth 29398a23840SMatthew Barth char *p; 29456003453SBrad Bishop uint8_t type; 29598a23840SMatthew Barth 29698a23840SMatthew Barth // This is where sensors that do not exist in dbus but do 29798a23840SMatthew Barth // exist in the host code stop. This should indicate it 29898a23840SMatthew Barth // is not a supported sensor 299391f3303SEmily Shaffer if (dbus_if.interface[0] == 0) { return 0;} 30098a23840SMatthew Barth 3017117441cSEmily Shaffer // Fetch type from interface itself. 3027117441cSEmily Shaffer if (dbus_if.sensortype != 0) 3037117441cSEmily Shaffer { 3047117441cSEmily Shaffer type = dbus_if.sensortype; 30598a23840SMatthew Barth } else { 30698a23840SMatthew Barth // Non InventoryItems 307391f3303SEmily Shaffer p = strrchr (dbus_if.path, '/'); 30856003453SBrad Bishop type = dbus_to_sensor_type(p+1); 30998a23840SMatthew Barth } 31098a23840SMatthew Barth 31156003453SBrad Bishop return type; 31298a23840SMatthew Barth } 31398a23840SMatthew Barth 314391f3303SEmily Shaffer // Replaces find_sensor 315391f3303SEmily Shaffer uint8_t find_type_for_sensor_number(uint8_t num) { 316391f3303SEmily Shaffer int r; 317391f3303SEmily Shaffer dbus_interface_t dbus_if; 3182ae09b9aSEmily Shaffer r = find_openbmc_path(num, &dbus_if); 319391f3303SEmily Shaffer if (r < 0) { 320391f3303SEmily Shaffer fprintf(stderr, "Could not find sensor %d\n", num); 32191875f77SLei YU return 0; 322391f3303SEmily Shaffer } 323391f3303SEmily Shaffer return get_type_from_interface(dbus_if); 324391f3303SEmily Shaffer } 325391f3303SEmily Shaffer 32698a23840SMatthew Barth 32798a23840SMatthew Barth 32898a23840SMatthew Barth 32998a23840SMatthew Barth 33098a23840SMatthew Barth ipmi_ret_t ipmi_sen_get_sensor_type(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 33198a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 33298a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 33398a23840SMatthew Barth { 33498a23840SMatthew Barth sensor_data_t *reqptr = (sensor_data_t*)request; 33598a23840SMatthew Barth ipmi_ret_t rc = IPMI_CC_OK; 33698a23840SMatthew Barth 33798a23840SMatthew Barth printf("IPMI GET_SENSOR_TYPE [0x%02X]\n",reqptr->sennum); 33898a23840SMatthew Barth 33998a23840SMatthew Barth // TODO Not sure what the System-event-sensor is suppose to return 34098a23840SMatthew Barth // need to ask Hostboot team 34198a23840SMatthew Barth unsigned char buf[] = {0x00,0x6F}; 34298a23840SMatthew Barth 343391f3303SEmily Shaffer buf[0] = find_type_for_sensor_number(reqptr->sennum); 34498a23840SMatthew Barth 34598a23840SMatthew Barth // HACK UNTIL Dbus gets updated or we find a better way 34698a23840SMatthew Barth if (buf[0] == 0) { 34798a23840SMatthew Barth rc = IPMI_CC_SENSOR_INVALID; 34898a23840SMatthew Barth } 34998a23840SMatthew Barth 35098a23840SMatthew Barth 35198a23840SMatthew Barth *data_len = sizeof(buf); 35298a23840SMatthew Barth memcpy(response, &buf, *data_len); 35398a23840SMatthew Barth 35498a23840SMatthew Barth return rc; 35598a23840SMatthew Barth } 35698a23840SMatthew Barth 357cc941e15SEmily Shaffer const std::set<std::string> analogSensorInterfaces = 358cc941e15SEmily Shaffer { 359cc941e15SEmily Shaffer "xyz.openbmc_project.Sensor.Value", 360e9a64056SPatrick Venture "xyz.openbmc_project.Control.FanPwm", 361cc941e15SEmily Shaffer }; 362cc941e15SEmily Shaffer 363cc941e15SEmily Shaffer bool isAnalogSensor(const std::string& interface) 364cc941e15SEmily Shaffer { 365cc941e15SEmily Shaffer return (analogSensorInterfaces.count(interface)); 366cc941e15SEmily Shaffer } 367cc941e15SEmily Shaffer 368be703f71STom Joseph ipmi_ret_t setSensorReading(void *request) 369be703f71STom Joseph { 370816e92b5STom Joseph ipmi::sensor::SetSensorReadingReq cmdData = 371816e92b5STom Joseph *(static_cast<ipmi::sensor::SetSensorReadingReq *>(request)); 372be703f71STom Joseph 373be703f71STom Joseph // Check if the Sensor Number is present 374e0af7209SDhruvaraj Subhashchandran const auto iter = sensors.find(cmdData.number); 375be703f71STom Joseph if (iter == sensors.end()) 376be703f71STom Joseph { 377be703f71STom Joseph return IPMI_CC_SENSOR_INVALID; 378be703f71STom Joseph } 379be703f71STom Joseph 38018e99992SDhruvaraj Subhashchandran try 38118e99992SDhruvaraj Subhashchandran { 3820922bde4SJayanth Othayoth if (ipmi::sensor::Mutability::Write != 3830922bde4SJayanth Othayoth (iter->second.mutability & ipmi::sensor::Mutability::Write)) 3840922bde4SJayanth Othayoth { 3850922bde4SJayanth Othayoth log<level::ERR>("Sensor Set operation is not allowed", 3860922bde4SJayanth Othayoth entry("SENSOR_NUM=%d", cmdData.number)); 3870922bde4SJayanth Othayoth return IPMI_CC_ILLEGAL_COMMAND; 3880922bde4SJayanth Othayoth } 389e0af7209SDhruvaraj Subhashchandran return iter->second.updateFunc(cmdData, iter->second); 390be703f71STom Joseph } 39118e99992SDhruvaraj Subhashchandran catch (InternalFailure& e) 39218e99992SDhruvaraj Subhashchandran { 39318e99992SDhruvaraj Subhashchandran log<level::ERR>("Set sensor failed", 39418e99992SDhruvaraj Subhashchandran entry("SENSOR_NUM=%d", cmdData.number)); 39518e99992SDhruvaraj Subhashchandran commit<InternalFailure>(); 39618e99992SDhruvaraj Subhashchandran } 3978202432fSTom Joseph catch (const std::runtime_error& e) 3988202432fSTom Joseph { 3998202432fSTom Joseph log<level::ERR>(e.what()); 4008202432fSTom Joseph } 40118e99992SDhruvaraj Subhashchandran 40218e99992SDhruvaraj Subhashchandran return IPMI_CC_UNSPECIFIED_ERROR; 40318e99992SDhruvaraj Subhashchandran } 40498a23840SMatthew Barth 40598a23840SMatthew Barth ipmi_ret_t ipmi_sen_set_sensor(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 40698a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 40798a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 40898a23840SMatthew Barth { 40998a23840SMatthew Barth sensor_data_t *reqptr = (sensor_data_t*)request; 41098a23840SMatthew Barth 41198a23840SMatthew Barth printf("IPMI SET_SENSOR [0x%02x]\n",reqptr->sennum); 41298a23840SMatthew Barth 413be703f71STom Joseph /* 414be703f71STom Joseph * This would support the Set Sensor Reading command for the presence 415be703f71STom Joseph * and functional state of Processor, Core & DIMM. For the remaining 416be703f71STom Joseph * sensors the existing support is invoked. 417be703f71STom Joseph */ 418be703f71STom Joseph auto ipmiRC = setSensorReading(request); 419be703f71STom Joseph 420be703f71STom Joseph if(ipmiRC == IPMI_CC_SENSOR_INVALID) 421be703f71STom Joseph { 42298a23840SMatthew Barth updateSensorRecordFromSSRAESC(reqptr); 423be703f71STom Joseph ipmiRC = IPMI_CC_OK; 424be703f71STom Joseph } 42598a23840SMatthew Barth 42698a23840SMatthew Barth *data_len=0; 427be703f71STom Joseph return ipmiRC; 42898a23840SMatthew Barth } 42998a23840SMatthew Barth 4303ee668f9STom Joseph ipmi_ret_t legacyGetSensorReading(uint8_t sensorNum, 4313ee668f9STom Joseph ipmi_response_t response, 4323ee668f9STom Joseph ipmi_data_len_t data_len) 43398a23840SMatthew Barth { 43498a23840SMatthew Barth int r; 43598a23840SMatthew Barth dbus_interface_t a; 43698a23840SMatthew Barth sd_bus *bus = ipmid_get_sd_bus_connection(); 4373ee668f9STom Joseph ipmi_ret_t rc = IPMI_CC_SENSOR_INVALID; 4383ee668f9STom Joseph uint8_t type = 0; 43998a23840SMatthew Barth sd_bus_message *reply = NULL; 44098a23840SMatthew Barth int reading = 0; 4416244f93dSDhruvaraj Subhashchandran char* assertion = NULL; 4423ee668f9STom Joseph sensorreadingresp_t *resp = (sensorreadingresp_t*) response; 4433ee668f9STom Joseph *data_len=0; 44498a23840SMatthew Barth 4453ee668f9STom Joseph r = find_openbmc_path(sensorNum, &a); 44640c35b1cSTom Joseph if (r < 0) 44740c35b1cSTom Joseph { 4483ee668f9STom Joseph sd_journal_print(LOG_ERR, "Failed to find Sensor 0x%02x\n", sensorNum); 44956003453SBrad Bishop return IPMI_CC_SENSOR_INVALID; 45056003453SBrad Bishop } 45198a23840SMatthew Barth 4523ee668f9STom Joseph type = get_type_from_interface(a); 4533ee668f9STom Joseph if (type == 0) 4543ee668f9STom Joseph { 4553ee668f9STom Joseph sd_journal_print(LOG_ERR, "Failed to find Sensor 0x%02x\n", 4563ee668f9STom Joseph sensorNum); 4573ee668f9STom Joseph return IPMI_CC_SENSOR_INVALID; 45840c35b1cSTom Joseph } 45998a23840SMatthew Barth 46098a23840SMatthew Barth switch(type) { 46198a23840SMatthew Barth case 0xC2: 462d12ae758SDhruvaraj Subhashchandran case 0xC8: 4633ee668f9STom Joseph r = sd_bus_get_property(bus,a.bus, a.path, a.interface, 4643ee668f9STom Joseph "value", NULL, &reply, "i"); 4653ee668f9STom Joseph if (r < 0) 4663ee668f9STom Joseph { 4673ee668f9STom Joseph sd_journal_print(LOG_ERR, "Failed to call sd_bus_get_property:" 4683ee668f9STom Joseph " %d, %s\n", r, strerror(-r)); 4693ee668f9STom Joseph sd_journal_print(LOG_ERR, "Bus: %s, Path: %s, Interface: %s\n", 47098a23840SMatthew Barth a.bus, a.path, a.interface); 47198a23840SMatthew Barth break; 47298a23840SMatthew Barth } 47398a23840SMatthew Barth 47498a23840SMatthew Barth r = sd_bus_message_read(reply, "i", &reading); 47598a23840SMatthew Barth if (r < 0) { 4763ee668f9STom Joseph sd_journal_print(LOG_ERR, "Failed to read sensor: %s\n", 4773ee668f9STom Joseph strerror(-r)); 47898a23840SMatthew Barth break; 47998a23840SMatthew Barth } 48098a23840SMatthew Barth 48198a23840SMatthew Barth rc = IPMI_CC_OK; 48298a23840SMatthew Barth *data_len=sizeof(sensorreadingresp_t); 48398a23840SMatthew Barth 48498a23840SMatthew Barth resp->value = (uint8_t)reading; 48598a23840SMatthew Barth resp->operation = 0; 48698a23840SMatthew Barth resp->indication[0] = 0; 48798a23840SMatthew Barth resp->indication[1] = 0; 48898a23840SMatthew Barth break; 48998a23840SMatthew Barth 4906244f93dSDhruvaraj Subhashchandran //TODO openbmc/openbmc#2154 Move this sensor to right place. 4916244f93dSDhruvaraj Subhashchandran case 0xCA: 4923ee668f9STom Joseph r = sd_bus_get_property(bus,a.bus, a.path, a.interface, "value", 4933ee668f9STom Joseph NULL, &reply, "s"); 4943ee668f9STom Joseph if (r < 0) 4953ee668f9STom Joseph { 4963ee668f9STom Joseph sd_journal_print(LOG_ERR, "Failed to call sd_bus_get_property:" 4973ee668f9STom Joseph " %d, %s\n", r, strerror(-r)); 4983ee668f9STom Joseph sd_journal_print(LOG_ERR, "Bus: %s, Path: %s, Interface: %s\n", 4996244f93dSDhruvaraj Subhashchandran a.bus, a.path, a.interface); 5006244f93dSDhruvaraj Subhashchandran break; 5016244f93dSDhruvaraj Subhashchandran } 5026244f93dSDhruvaraj Subhashchandran 5036244f93dSDhruvaraj Subhashchandran r = sd_bus_message_read(reply, "s", &assertion); 5043ee668f9STom Joseph if (r < 0) 5053ee668f9STom Joseph { 5063ee668f9STom Joseph sd_journal_print(LOG_ERR, "Failed to read sensor: %s\n", 5073ee668f9STom Joseph strerror(-r)); 5086244f93dSDhruvaraj Subhashchandran break; 5096244f93dSDhruvaraj Subhashchandran } 5106244f93dSDhruvaraj Subhashchandran 5116244f93dSDhruvaraj Subhashchandran rc = IPMI_CC_OK; 5126244f93dSDhruvaraj Subhashchandran *data_len=sizeof(sensorreadingresp_t); 5136244f93dSDhruvaraj Subhashchandran 5146244f93dSDhruvaraj Subhashchandran resp->value = 0; 5156244f93dSDhruvaraj Subhashchandran resp->operation = 0; 5166244f93dSDhruvaraj Subhashchandran if (strcmp(assertion,"Enabled") == 0) 5176244f93dSDhruvaraj Subhashchandran { 5186244f93dSDhruvaraj Subhashchandran resp->indication[0] = 0x02; 5196244f93dSDhruvaraj Subhashchandran } 5206244f93dSDhruvaraj Subhashchandran else 5216244f93dSDhruvaraj Subhashchandran { 5226244f93dSDhruvaraj Subhashchandran resp->indication[0] = 0x1; 5236244f93dSDhruvaraj Subhashchandran } 5246244f93dSDhruvaraj Subhashchandran resp->indication[1] = 0; 5256244f93dSDhruvaraj Subhashchandran break; 5266244f93dSDhruvaraj Subhashchandran 52798a23840SMatthew Barth default: 52814c15467STom Joseph { 5293ee668f9STom Joseph return IPMI_CC_SENSOR_INVALID; 5303ee668f9STom Joseph } 5313ee668f9STom Joseph } 5323ee668f9STom Joseph 5333ee668f9STom Joseph reply = sd_bus_message_unref(reply); 5343ee668f9STom Joseph 5353ee668f9STom Joseph return rc; 5363ee668f9STom Joseph } 5373ee668f9STom Joseph 5383ee668f9STom Joseph ipmi_ret_t ipmi_sen_get_sensor_reading(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 5393ee668f9STom Joseph ipmi_request_t request, ipmi_response_t response, 5403ee668f9STom Joseph ipmi_data_len_t data_len, ipmi_context_t context) 5413ee668f9STom Joseph { 5423ee668f9STom Joseph sensor_data_t *reqptr = (sensor_data_t*)request; 5433ee668f9STom Joseph sensorreadingresp_t *resp = (sensorreadingresp_t*) response; 5443ee668f9STom Joseph ipmi::sensor::GetSensorResponse getResponse {}; 5453ee668f9STom Joseph static constexpr auto scanningEnabledBit = 6; 5463ee668f9STom Joseph 54714c15467STom Joseph const auto iter = sensors.find(reqptr->sennum); 54814c15467STom Joseph if (iter == sensors.end()) 54914c15467STom Joseph { 5503ee668f9STom Joseph return legacyGetSensorReading(reqptr->sennum, response, data_len); 55114c15467STom Joseph } 55213b87a3eSTom Joseph if (ipmi::sensor::Mutability::Read != 55313b87a3eSTom Joseph (iter->second.mutability & ipmi::sensor::Mutability::Read)) 55413b87a3eSTom Joseph { 555*6ccf8818SJayanth Othayoth return IPMI_CC_ILLEGAL_COMMAND; 55613b87a3eSTom Joseph } 55714c15467STom Joseph 55814c15467STom Joseph try 55914c15467STom Joseph { 560c6162fb6STom Joseph getResponse = iter->second.getFunc(iter->second); 56114c15467STom Joseph *data_len = getResponse.size(); 56214c15467STom Joseph memcpy(resp, getResponse.data(), *data_len); 563c6162fb6STom Joseph resp->operation = 1 << scanningEnabledBit; 56414c15467STom Joseph return IPMI_CC_OK; 56514c15467STom Joseph } 5663ee668f9STom Joseph catch (const std::exception& e) 56714c15467STom Joseph { 568c6162fb6STom Joseph *data_len = getResponse.size(); 569c6162fb6STom Joseph memcpy(resp, getResponse.data(), *data_len); 570c6162fb6STom Joseph return IPMI_CC_OK; 57114c15467STom Joseph } 57298a23840SMatthew Barth } 57398a23840SMatthew Barth 5740ac0dd23STom Joseph void getSensorThresholds(uint8_t sensorNum, 5750ac0dd23STom Joseph get_sdr::GetSensorThresholdsResponse* response) 5760ac0dd23STom Joseph { 5770ac0dd23STom Joseph constexpr auto warningThreshIntf = 5780ac0dd23STom Joseph "xyz.openbmc_project.Sensor.Threshold.Warning"; 5790ac0dd23STom Joseph constexpr auto criticalThreshIntf = 5800ac0dd23STom Joseph "xyz.openbmc_project.Sensor.Threshold.Critical"; 5810ac0dd23STom Joseph 5820ac0dd23STom Joseph sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; 5830ac0dd23STom Joseph 5840ac0dd23STom Joseph const auto iter = sensors.find(sensorNum); 5850ac0dd23STom Joseph const auto info = iter->second; 5860ac0dd23STom Joseph 5870ac0dd23STom Joseph auto service = ipmi::getService(bus, info.sensorInterface, info.sensorPath); 5880ac0dd23STom Joseph 5890ac0dd23STom Joseph auto warnThresholds = ipmi::getAllDbusProperties(bus, 5900ac0dd23STom Joseph service, 5910ac0dd23STom Joseph info.sensorPath, 5920ac0dd23STom Joseph warningThreshIntf); 5930ac0dd23STom Joseph 5940ac0dd23STom Joseph double warnLow = warnThresholds["WarningLow"].get<int64_t>(); 5950ac0dd23STom Joseph double warnHigh = warnThresholds["WarningHigh"].get<int64_t>(); 5960ac0dd23STom Joseph 5970ac0dd23STom Joseph if (warnLow != 0) 5980ac0dd23STom Joseph { 5990ac0dd23STom Joseph warnLow *= pow(10, info.scale - info.exponentR); 6000ac0dd23STom Joseph response->lowerNonCritical = static_cast<uint8_t>(( 6010ac0dd23STom Joseph warnLow - info.scaledOffset) / info.coefficientM); 6020ac0dd23STom Joseph response->validMask |= static_cast<uint8_t>( 6030ac0dd23STom Joseph ipmi::sensor::ThresholdMask::NON_CRITICAL_LOW_MASK); 6040ac0dd23STom Joseph } 6050ac0dd23STom Joseph 6060ac0dd23STom Joseph if (warnHigh != 0) 6070ac0dd23STom Joseph { 6080ac0dd23STom Joseph warnHigh *= pow(10, info.scale - info.exponentR); 6090ac0dd23STom Joseph response->upperNonCritical = static_cast<uint8_t>(( 6100ac0dd23STom Joseph warnHigh - info.scaledOffset) / info.coefficientM); 6110ac0dd23STom Joseph response->validMask |= static_cast<uint8_t>( 6120ac0dd23STom Joseph ipmi::sensor::ThresholdMask::NON_CRITICAL_HIGH_MASK); 6130ac0dd23STom Joseph } 6140ac0dd23STom Joseph 6150ac0dd23STom Joseph auto critThresholds = ipmi::getAllDbusProperties(bus, 6160ac0dd23STom Joseph service, 6170ac0dd23STom Joseph info.sensorPath, 6180ac0dd23STom Joseph criticalThreshIntf); 6190ac0dd23STom Joseph double critLow = critThresholds["CriticalLow"].get<int64_t>(); 6200ac0dd23STom Joseph double critHigh = critThresholds["CriticalHigh"].get<int64_t>(); 6210ac0dd23STom Joseph 6220ac0dd23STom Joseph if (critLow != 0) 6230ac0dd23STom Joseph { 6240ac0dd23STom Joseph critLow *= pow(10, info.scale - info.exponentR); 6250ac0dd23STom Joseph response->lowerCritical = static_cast<uint8_t>(( 6260ac0dd23STom Joseph critLow - info.scaledOffset) / info.coefficientM); 6270ac0dd23STom Joseph response->validMask |= static_cast<uint8_t>( 6280ac0dd23STom Joseph ipmi::sensor::ThresholdMask::CRITICAL_LOW_MASK); 6290ac0dd23STom Joseph } 6300ac0dd23STom Joseph 6310ac0dd23STom Joseph if (critHigh != 0) 6320ac0dd23STom Joseph { 6330ac0dd23STom Joseph critHigh *= pow(10, info.scale - info.exponentR); 6340ac0dd23STom Joseph response->upperCritical = static_cast<uint8_t>(( 6350ac0dd23STom Joseph critHigh - info.scaledOffset)/ info.coefficientM); 6360ac0dd23STom Joseph response->validMask |= static_cast<uint8_t>( 6370ac0dd23STom Joseph ipmi::sensor::ThresholdMask::CRITICAL_HIGH_MASK); 6380ac0dd23STom Joseph } 6390ac0dd23STom Joseph } 6400ac0dd23STom Joseph 6415c0beec1SDhruvaraj Subhashchandran ipmi_ret_t ipmi_sen_get_sensor_thresholds(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 6425c0beec1SDhruvaraj Subhashchandran ipmi_request_t request, ipmi_response_t response, 6435c0beec1SDhruvaraj Subhashchandran ipmi_data_len_t data_len, ipmi_context_t context) 6445c0beec1SDhruvaraj Subhashchandran { 6450ac0dd23STom Joseph constexpr auto valueInterface = "xyz.openbmc_project.Sensor.Value"; 6465c0beec1SDhruvaraj Subhashchandran 6475c0beec1SDhruvaraj Subhashchandran if (*data_len != sizeof(uint8_t)) 6485c0beec1SDhruvaraj Subhashchandran { 6490ac0dd23STom Joseph *data_len = 0; 6505c0beec1SDhruvaraj Subhashchandran return IPMI_CC_REQ_DATA_LEN_INVALID; 6515c0beec1SDhruvaraj Subhashchandran } 6525c0beec1SDhruvaraj Subhashchandran 6530ac0dd23STom Joseph auto sensorNum = *(reinterpret_cast<const uint8_t *>(request)); 6540ac0dd23STom Joseph *data_len = 0; 6555c0beec1SDhruvaraj Subhashchandran 6565c0beec1SDhruvaraj Subhashchandran const auto iter = sensors.find(sensorNum); 6575c0beec1SDhruvaraj Subhashchandran if (iter == sensors.end()) 6585c0beec1SDhruvaraj Subhashchandran { 6595c0beec1SDhruvaraj Subhashchandran return IPMI_CC_SENSOR_INVALID; 6605c0beec1SDhruvaraj Subhashchandran } 6615c0beec1SDhruvaraj Subhashchandran 6620ac0dd23STom Joseph const auto info = iter->second; 6635c0beec1SDhruvaraj Subhashchandran 6645c0beec1SDhruvaraj Subhashchandran //Proceed only if the sensor value interface is implemented. 6650ac0dd23STom Joseph if (info.propertyInterfaces.find(valueInterface) == 6660ac0dd23STom Joseph info.propertyInterfaces.end()) 6675c0beec1SDhruvaraj Subhashchandran { 6685c0beec1SDhruvaraj Subhashchandran //return with valid mask as 0 6695c0beec1SDhruvaraj Subhashchandran return IPMI_CC_OK; 6705c0beec1SDhruvaraj Subhashchandran } 6715c0beec1SDhruvaraj Subhashchandran 6720ac0dd23STom Joseph auto responseData = 6730ac0dd23STom Joseph reinterpret_cast<get_sdr::GetSensorThresholdsResponse*>(response); 6745c0beec1SDhruvaraj Subhashchandran 6755c0beec1SDhruvaraj Subhashchandran try 6765c0beec1SDhruvaraj Subhashchandran { 6770ac0dd23STom Joseph getSensorThresholds(sensorNum, responseData); 6785c0beec1SDhruvaraj Subhashchandran } 6790ac0dd23STom Joseph catch (std::exception& e) 6805c0beec1SDhruvaraj Subhashchandran { 6810ac0dd23STom Joseph //Mask if the property is not present 6825c0beec1SDhruvaraj Subhashchandran responseData->validMask = 0; 6835c0beec1SDhruvaraj Subhashchandran } 6845c0beec1SDhruvaraj Subhashchandran 6855c0beec1SDhruvaraj Subhashchandran *data_len = sizeof(get_sdr::GetSensorThresholdsResponse); 6865c0beec1SDhruvaraj Subhashchandran return IPMI_CC_OK; 6875c0beec1SDhruvaraj Subhashchandran } 6885c0beec1SDhruvaraj Subhashchandran 68998a23840SMatthew Barth ipmi_ret_t ipmi_sen_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 69098a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 69198a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 69298a23840SMatthew Barth { 69370aa8d96SNan Li ipmi_ret_t rc = IPMI_CC_INVALID; 69498a23840SMatthew Barth 69598a23840SMatthew Barth printf("IPMI S/E Wildcard Netfn:[0x%X], Cmd:[0x%X]\n",netfn,cmd); 69698a23840SMatthew Barth *data_len = 0; 69798a23840SMatthew Barth 69898a23840SMatthew Barth return rc; 69998a23840SMatthew Barth } 70098a23840SMatthew Barth 701d06e0e7eSEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 702d06e0e7eSEmily Shaffer ipmi_request_t request, 703d06e0e7eSEmily Shaffer ipmi_response_t response, 704d06e0e7eSEmily Shaffer ipmi_data_len_t data_len, 705d06e0e7eSEmily Shaffer ipmi_context_t context) 706d06e0e7eSEmily Shaffer { 707d06e0e7eSEmily Shaffer auto resp = static_cast<get_sdr_info::GetSdrInfoResp*>(response); 708d06e0e7eSEmily Shaffer if (request == nullptr || 709d06e0e7eSEmily Shaffer get_sdr_info::request::get_count(request) == false) 710d06e0e7eSEmily Shaffer { 711d06e0e7eSEmily Shaffer // Get Sensor Count 712e0cc8553SRatan Gupta resp->count = sensors.size() + frus.size(); 713d06e0e7eSEmily Shaffer } 714d06e0e7eSEmily Shaffer else 715d06e0e7eSEmily Shaffer { 716d06e0e7eSEmily Shaffer resp->count = 1; 717d06e0e7eSEmily Shaffer } 718d06e0e7eSEmily Shaffer 719d06e0e7eSEmily Shaffer // Multiple LUNs not supported. 720d06e0e7eSEmily Shaffer namespace response = get_sdr_info::response; 721d06e0e7eSEmily Shaffer response::set_lun_present(0, &(resp->luns_and_dynamic_population)); 722d06e0e7eSEmily Shaffer response::set_lun_not_present(1, &(resp->luns_and_dynamic_population)); 723d06e0e7eSEmily Shaffer response::set_lun_not_present(2, &(resp->luns_and_dynamic_population)); 724d06e0e7eSEmily Shaffer response::set_lun_not_present(3, &(resp->luns_and_dynamic_population)); 725d06e0e7eSEmily Shaffer response::set_static_population(&(resp->luns_and_dynamic_population)); 726d06e0e7eSEmily Shaffer 727d06e0e7eSEmily Shaffer *data_len = SDR_INFO_RESP_SIZE; 728d06e0e7eSEmily Shaffer 729d06e0e7eSEmily Shaffer return IPMI_CC_OK; 730d06e0e7eSEmily Shaffer } 731d06e0e7eSEmily Shaffer 732a344afc0SEmily Shaffer ipmi_ret_t ipmi_sen_reserve_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 733a344afc0SEmily Shaffer ipmi_request_t request, 734a344afc0SEmily Shaffer ipmi_response_t response, 735a344afc0SEmily Shaffer ipmi_data_len_t data_len, 736a344afc0SEmily Shaffer ipmi_context_t context) 737a344afc0SEmily Shaffer { 738a344afc0SEmily Shaffer // A constant reservation ID is okay until we implement add/remove SDR. 739a344afc0SEmily Shaffer const uint16_t reservation_id = 1; 740a344afc0SEmily Shaffer *(uint16_t*)response = reservation_id; 7415a5a6282SEmily Shaffer *data_len = sizeof(uint16_t); 742a344afc0SEmily Shaffer 743a344afc0SEmily Shaffer printf("Created new IPMI SDR reservation ID %d\n", *(uint16_t*)response); 744a344afc0SEmily Shaffer return IPMI_CC_OK; 745a344afc0SEmily Shaffer } 74698a23840SMatthew Barth 747dc212b23STom Joseph void setUnitFieldsForObject(const ipmi::sensor::Info *info, 748cc941e15SEmily Shaffer get_sdr::SensorDataFullRecordBody *body) 749bbef71c2SEmily Shaffer { 750bbef71c2SEmily Shaffer namespace server = sdbusplus::xyz::openbmc_project::Sensor::server; 751dc212b23STom Joseph try 752dc212b23STom Joseph { 753dc212b23STom Joseph auto unit = server::Value::convertUnitFromString(info->unit); 754bbef71c2SEmily Shaffer // Unit strings defined in 755bbef71c2SEmily Shaffer // phosphor-dbus-interfaces/xyz/openbmc_project/Sensor/Value.interface.yaml 756bbef71c2SEmily Shaffer switch (unit) 757bbef71c2SEmily Shaffer { 758bbef71c2SEmily Shaffer case server::Value::Unit::DegreesC: 759bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_DEGREES_C; 760bbef71c2SEmily Shaffer break; 761bbef71c2SEmily Shaffer case server::Value::Unit::RPMS: 762bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_REVOLUTIONS; // revolutions 763bbef71c2SEmily Shaffer get_sdr::body::set_rate_unit(0b100, body); // per minute 764bbef71c2SEmily Shaffer break; 765bbef71c2SEmily Shaffer case server::Value::Unit::Volts: 766bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_VOLTS; 767bbef71c2SEmily Shaffer break; 768bbef71c2SEmily Shaffer case server::Value::Unit::Meters: 769bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_METERS; 770bbef71c2SEmily Shaffer break; 771bbef71c2SEmily Shaffer case server::Value::Unit::Amperes: 772bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_AMPERES; 773bbef71c2SEmily Shaffer break; 774bbef71c2SEmily Shaffer case server::Value::Unit::Joules: 775bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_JOULES; 776bbef71c2SEmily Shaffer break; 777dc212b23STom Joseph case server::Value::Unit::Watts: 778dc212b23STom Joseph body->sensor_units_2_base = get_sdr::SENSOR_UNIT_WATTS; 779dc212b23STom Joseph break; 780bbef71c2SEmily Shaffer default: 781cc941e15SEmily Shaffer // Cannot be hit. 782dc212b23STom Joseph fprintf(stderr, "Unknown value unit type: = %s\n", 783dc212b23STom Joseph info->unit.c_str()); 784cc941e15SEmily Shaffer } 785cc941e15SEmily Shaffer } 786cc941e15SEmily Shaffer catch (sdbusplus::exception::InvalidEnumString e) 787cc941e15SEmily Shaffer { 788cc941e15SEmily Shaffer log<level::WARNING>("Warning: no unit provided for sensor!"); 789cc941e15SEmily Shaffer } 790cc941e15SEmily Shaffer } 791cc941e15SEmily Shaffer 792cc941e15SEmily Shaffer ipmi_ret_t populate_record_from_dbus(get_sdr::SensorDataFullRecordBody *body, 793cc941e15SEmily Shaffer const ipmi::sensor::Info *info, 794cc941e15SEmily Shaffer ipmi_data_len_t data_len) 795cc941e15SEmily Shaffer { 796cc941e15SEmily Shaffer /* Functional sensor case */ 797cc941e15SEmily Shaffer if (isAnalogSensor(info->propertyInterfaces.begin()->first)) 798cc941e15SEmily Shaffer { 799cc941e15SEmily Shaffer 800cc941e15SEmily Shaffer body->sensor_units_1 = 0; // unsigned, no rate, no modifier, not a % 801cc941e15SEmily Shaffer 802cc941e15SEmily Shaffer /* Unit info */ 803dc212b23STom Joseph setUnitFieldsForObject(info, body); 80410f4959aSEmily Shaffer 80510f4959aSEmily Shaffer get_sdr::body::set_b(info->coefficientB, body); 80610f4959aSEmily Shaffer get_sdr::body::set_m(info->coefficientM, body); 80710f4959aSEmily Shaffer get_sdr::body::set_b_exp(info->exponentB, body); 808dc212b23STom Joseph get_sdr::body::set_r_exp(info->exponentR, body); 809bbef71c2SEmily Shaffer 810bbef71c2SEmily Shaffer get_sdr::body::set_id_type(0b00, body); // 00 = unicode 8119642391dSTom Joseph } 8129642391dSTom Joseph 8139642391dSTom Joseph /* ID string */ 8149642391dSTom Joseph auto id_string = info->sensorNameFunc(*info); 8159642391dSTom Joseph 816bbef71c2SEmily Shaffer if (id_string.length() > FULL_RECORD_ID_STR_MAX_LENGTH) 817bbef71c2SEmily Shaffer { 818bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(FULL_RECORD_ID_STR_MAX_LENGTH, body); 819bbef71c2SEmily Shaffer } 820bbef71c2SEmily Shaffer else 821bbef71c2SEmily Shaffer { 822bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(id_string.length(), body); 823bbef71c2SEmily Shaffer } 824bbef71c2SEmily Shaffer strncpy(body->id_string, id_string.c_str(), 825bbef71c2SEmily Shaffer get_sdr::body::get_id_strlen(body)); 826bbef71c2SEmily Shaffer 827bbef71c2SEmily Shaffer return IPMI_CC_OK; 828bbef71c2SEmily Shaffer }; 829bbef71c2SEmily Shaffer 830e0cc8553SRatan Gupta ipmi_ret_t ipmi_fru_get_sdr(ipmi_request_t request, ipmi_response_t response, 831e0cc8553SRatan Gupta ipmi_data_len_t data_len) 832e0cc8553SRatan Gupta { 833e0cc8553SRatan Gupta auto req = reinterpret_cast<get_sdr::GetSdrReq*>(request); 834e0cc8553SRatan Gupta auto resp = reinterpret_cast<get_sdr::GetSdrResp*>(response); 835e0cc8553SRatan Gupta get_sdr::SensorDataFruRecord record {}; 836e0cc8553SRatan Gupta auto dataLength = 0; 837e0cc8553SRatan Gupta 838e0cc8553SRatan Gupta auto fru = frus.begin(); 839e0cc8553SRatan Gupta uint8_t fruID {}; 840e0cc8553SRatan Gupta auto recordID = get_sdr::request::get_record_id(req); 841e0cc8553SRatan Gupta 842e0cc8553SRatan Gupta fruID = recordID - FRU_RECORD_ID_START; 843e0cc8553SRatan Gupta fru = frus.find(fruID); 844e0cc8553SRatan Gupta if (fru == frus.end()) 845e0cc8553SRatan Gupta { 846e0cc8553SRatan Gupta return IPMI_CC_SENSOR_INVALID; 847e0cc8553SRatan Gupta } 848e0cc8553SRatan Gupta 849e0cc8553SRatan Gupta /* Header */ 850e0cc8553SRatan Gupta get_sdr::header::set_record_id(recordID, &(record.header)); 851e0cc8553SRatan Gupta record.header.sdr_version = SDR_VERSION; // Based on IPMI Spec v2.0 rev 1.1 852e0cc8553SRatan Gupta record.header.record_type = get_sdr::SENSOR_DATA_FRU_RECORD; 853e0cc8553SRatan Gupta record.header.record_length = sizeof(record.key) + sizeof(record.body); 854e0cc8553SRatan Gupta 855e0cc8553SRatan Gupta /* Key */ 856e0cc8553SRatan Gupta record.key.fruID = fruID; 857e0cc8553SRatan Gupta record.key.accessLun |= IPMI_LOGICAL_FRU; 858e0cc8553SRatan Gupta record.key.deviceAddress = BMCSlaveAddress; 859e0cc8553SRatan Gupta 860e0cc8553SRatan Gupta /* Body */ 861e0cc8553SRatan Gupta record.body.entityID = fru->second[0].entityID; 862e0cc8553SRatan Gupta record.body.entityInstance = fru->second[0].entityInstance; 863e0cc8553SRatan Gupta record.body.deviceType = fruInventoryDevice; 864e0cc8553SRatan Gupta record.body.deviceTypeModifier = IPMIFruInventory; 865e0cc8553SRatan Gupta 866e0cc8553SRatan Gupta /* Device ID string */ 867e0cc8553SRatan Gupta auto deviceID = fru->second[0].path.substr( 868e0cc8553SRatan Gupta fru->second[0].path.find_last_of('/') + 1, 869e0cc8553SRatan Gupta fru->second[0].path.length()); 870e0cc8553SRatan Gupta 871e0cc8553SRatan Gupta 872e0cc8553SRatan Gupta if (deviceID.length() > get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH) 873e0cc8553SRatan Gupta { 874e0cc8553SRatan Gupta get_sdr::body::set_device_id_strlen( 875e0cc8553SRatan Gupta get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH, 876e0cc8553SRatan Gupta &(record.body)); 877e0cc8553SRatan Gupta } 878e0cc8553SRatan Gupta else 879e0cc8553SRatan Gupta { 880e0cc8553SRatan Gupta get_sdr::body::set_device_id_strlen(deviceID.length(), 881e0cc8553SRatan Gupta &(record.body)); 882e0cc8553SRatan Gupta } 883e0cc8553SRatan Gupta 884e0cc8553SRatan Gupta strncpy(record.body.deviceID, deviceID.c_str(), 885e0cc8553SRatan Gupta get_sdr::body::get_device_id_strlen(&(record.body))); 886e0cc8553SRatan Gupta 887e0cc8553SRatan Gupta if (++fru == frus.end()) 888e0cc8553SRatan Gupta { 889e0cc8553SRatan Gupta get_sdr::response::set_next_record_id(END_OF_RECORD, resp); // last record 890e0cc8553SRatan Gupta } 891e0cc8553SRatan Gupta else 892e0cc8553SRatan Gupta { 893e0cc8553SRatan Gupta get_sdr::response::set_next_record_id( 894e0cc8553SRatan Gupta (FRU_RECORD_ID_START + fru->first), resp); 895e0cc8553SRatan Gupta } 896e0cc8553SRatan Gupta 897e0cc8553SRatan Gupta if (req->bytes_to_read > (sizeof(*resp) - req->offset)) 898e0cc8553SRatan Gupta { 899e0cc8553SRatan Gupta dataLength = (sizeof(*resp) - req->offset); 900e0cc8553SRatan Gupta } 901e0cc8553SRatan Gupta else 902e0cc8553SRatan Gupta { 903e0cc8553SRatan Gupta dataLength = req->bytes_to_read; 904e0cc8553SRatan Gupta } 905e0cc8553SRatan Gupta 906e0cc8553SRatan Gupta if (dataLength <= 0) 907e0cc8553SRatan Gupta { 908e0cc8553SRatan Gupta return IPMI_CC_REQ_DATA_LEN_INVALID; 909e0cc8553SRatan Gupta } 910e0cc8553SRatan Gupta 911e0cc8553SRatan Gupta memcpy(resp->record_data, 912e0cc8553SRatan Gupta reinterpret_cast<uint8_t*>(&record) + req->offset, 913e0cc8553SRatan Gupta (dataLength)); 914e0cc8553SRatan Gupta 915e0cc8553SRatan Gupta *data_len = dataLength; 916e0cc8553SRatan Gupta *data_len += 2; // additional 2 bytes for next record ID 917e0cc8553SRatan Gupta 918e0cc8553SRatan Gupta return IPMI_CC_OK; 919e0cc8553SRatan Gupta } 920e0cc8553SRatan Gupta 921bbef71c2SEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 922bbef71c2SEmily Shaffer ipmi_request_t request, ipmi_response_t response, 923bbef71c2SEmily Shaffer ipmi_data_len_t data_len, ipmi_context_t context) 924bbef71c2SEmily Shaffer { 925bbef71c2SEmily Shaffer ipmi_ret_t ret = IPMI_CC_OK; 926bbef71c2SEmily Shaffer get_sdr::GetSdrReq *req = (get_sdr::GetSdrReq*)request; 927bbef71c2SEmily Shaffer get_sdr::GetSdrResp *resp = (get_sdr::GetSdrResp*)response; 928bbef71c2SEmily Shaffer get_sdr::SensorDataFullRecord record = {0}; 929bbef71c2SEmily Shaffer if (req != NULL) 930bbef71c2SEmily Shaffer { 931bbef71c2SEmily Shaffer // Note: we use an iterator so we can provide the next ID at the end of 932bbef71c2SEmily Shaffer // the call. 933bbef71c2SEmily Shaffer auto sensor = sensors.begin(); 934e0cc8553SRatan Gupta auto recordID = get_sdr::request::get_record_id(req); 935bbef71c2SEmily Shaffer 936bbef71c2SEmily Shaffer // At the beginning of a scan, the host side will send us id=0. 937e0cc8553SRatan Gupta if (recordID != 0) 938bbef71c2SEmily Shaffer { 939e0cc8553SRatan Gupta // recordID greater then 255,it means it is a FRU record. 940e0cc8553SRatan Gupta // Currently we are supporting two record types either FULL record 941e0cc8553SRatan Gupta // or FRU record. 942e0cc8553SRatan Gupta if (recordID >= FRU_RECORD_ID_START) 943e0cc8553SRatan Gupta { 944e0cc8553SRatan Gupta return ipmi_fru_get_sdr(request, response, data_len); 945e0cc8553SRatan Gupta } 946e0cc8553SRatan Gupta else 947e0cc8553SRatan Gupta { 948e0cc8553SRatan Gupta sensor = sensors.find(recordID); 949e0cc8553SRatan Gupta if (sensor == sensors.end()) 950e0cc8553SRatan Gupta { 951bbef71c2SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 952bbef71c2SEmily Shaffer } 953bbef71c2SEmily Shaffer } 954e0cc8553SRatan Gupta } 955bbef71c2SEmily Shaffer 956bbef71c2SEmily Shaffer uint8_t sensor_id = sensor->first; 957bbef71c2SEmily Shaffer 958bbef71c2SEmily Shaffer /* Header */ 959bbef71c2SEmily Shaffer get_sdr::header::set_record_id(sensor_id, &(record.header)); 960bbef71c2SEmily Shaffer record.header.sdr_version = 0x51; // Based on IPMI Spec v2.0 rev 1.1 961bbef71c2SEmily Shaffer record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD; 962bbef71c2SEmily Shaffer record.header.record_length = sizeof(get_sdr::SensorDataFullRecord); 963bbef71c2SEmily Shaffer 964bbef71c2SEmily Shaffer /* Key */ 9659642391dSTom Joseph get_sdr::key::set_owner_id_bmc(&(record.key)); 966bbef71c2SEmily Shaffer record.key.sensor_number = sensor_id; 967bbef71c2SEmily Shaffer 968bbef71c2SEmily Shaffer /* Body */ 9699642391dSTom Joseph record.body.entity_id = sensor->second.entityType; 970bbef71c2SEmily Shaffer record.body.sensor_type = sensor->second.sensorType; 971bbef71c2SEmily Shaffer record.body.event_reading_type = sensor->second.sensorReadingType; 9729642391dSTom Joseph record.body.entity_instance = sensor->second.instance; 973bbef71c2SEmily Shaffer 974bbef71c2SEmily Shaffer // Set the type-specific details given the DBus interface 975bbef71c2SEmily Shaffer ret = populate_record_from_dbus(&(record.body), &(sensor->second), 976bbef71c2SEmily Shaffer data_len); 977bbef71c2SEmily Shaffer 978bbef71c2SEmily Shaffer if (++sensor == sensors.end()) 979bbef71c2SEmily Shaffer { 980e0cc8553SRatan Gupta // we have reached till end of sensor, so assign the next record id 981e0cc8553SRatan Gupta // to 256(Max Sensor ID = 255) + FRU ID(may start with 0). 982e0cc8553SRatan Gupta auto next_record_id = (frus.size()) ? 983e0cc8553SRatan Gupta frus.begin()->first + FRU_RECORD_ID_START : 984e0cc8553SRatan Gupta END_OF_RECORD; 985e0cc8553SRatan Gupta 986e0cc8553SRatan Gupta get_sdr::response::set_next_record_id(next_record_id, resp); 987bbef71c2SEmily Shaffer } 988bbef71c2SEmily Shaffer else 989bbef71c2SEmily Shaffer { 990bbef71c2SEmily Shaffer get_sdr::response::set_next_record_id(sensor->first, resp); 991bbef71c2SEmily Shaffer } 992bbef71c2SEmily Shaffer 993bbef71c2SEmily Shaffer *data_len = sizeof(get_sdr::GetSdrResp) - req->offset; 994bbef71c2SEmily Shaffer memcpy(resp->record_data, (char*)&record + req->offset, 995bbef71c2SEmily Shaffer sizeof(get_sdr::SensorDataFullRecord) - req->offset); 996bbef71c2SEmily Shaffer } 997bbef71c2SEmily Shaffer 998bbef71c2SEmily Shaffer return ret; 999bbef71c2SEmily Shaffer } 1000bbef71c2SEmily Shaffer 1001bbef71c2SEmily Shaffer 100298a23840SMatthew Barth void register_netfn_sen_functions() 100398a23840SMatthew Barth { 10040573237fSTom // <Wildcard Command> 1005a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 1006a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_WILDCARD); 1007a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_WILDCARD, 1008a344afc0SEmily Shaffer nullptr, ipmi_sen_wildcard, 10090573237fSTom PRIVILEGE_USER); 101098a23840SMatthew Barth 10110573237fSTom // <Get Sensor Type> 1012a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 1013a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE); 1014a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE, 1015a344afc0SEmily Shaffer nullptr, ipmi_sen_get_sensor_type, 10160573237fSTom PRIVILEGE_USER); 101798a23840SMatthew Barth 10180573237fSTom // <Set Sensor Reading and Event Status> 1019a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 1020a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_SET_SENSOR); 1021a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_SET_SENSOR, 1022a344afc0SEmily Shaffer nullptr, ipmi_sen_set_sensor, 10230573237fSTom PRIVILEGE_OPERATOR); 102498a23840SMatthew Barth 10250573237fSTom // <Get Sensor Reading> 1026a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 1027a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING); 1028a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING, 1029a344afc0SEmily Shaffer nullptr, ipmi_sen_get_sensor_reading, 1030a344afc0SEmily Shaffer PRIVILEGE_USER); 1031a344afc0SEmily Shaffer 10325ca50959STom Joseph // <Reserve Device SDR Repository> 10335ca50959STom Joseph ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_RESERVE_DEVICE_SDR_REPO, 1034a344afc0SEmily Shaffer nullptr, ipmi_sen_reserve_sdr, 1035a344afc0SEmily Shaffer PRIVILEGE_USER); 103698a23840SMatthew Barth 10375ca50959STom Joseph // <Get Device SDR Info> 10385ca50959STom Joseph ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_DEVICE_SDR_INFO, 1039a344afc0SEmily Shaffer nullptr, ipmi_sen_get_sdr_info, 1040a344afc0SEmily Shaffer PRIVILEGE_USER); 1041bbef71c2SEmily Shaffer 10425ca50959STom Joseph // <Get Device SDR> 10435ca50959STom Joseph ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_DEVICE_SDR, 1044bbef71c2SEmily Shaffer nullptr, ipmi_sen_get_sdr, 1045bbef71c2SEmily Shaffer PRIVILEGE_USER); 1046bbef71c2SEmily Shaffer 10475c0beec1SDhruvaraj Subhashchandran // <Get Sensor Thresholds> 10485c0beec1SDhruvaraj Subhashchandran ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_THRESHOLDS, 10495c0beec1SDhruvaraj Subhashchandran nullptr, ipmi_sen_get_sensor_thresholds, 10505c0beec1SDhruvaraj Subhashchandran PRIVILEGE_USER); 10515c0beec1SDhruvaraj Subhashchandran 105298a23840SMatthew Barth return; 105398a23840SMatthew Barth } 1054