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> 12d700e76aSTom #include "ipmid.hpp" 13be703f71STom Joseph #include "sensorhandler.h" 14be703f71STom Joseph #include "types.hpp" 15be703f71STom Joseph #include "utils.hpp" 1618e99992SDhruvaraj Subhashchandran #include "xyz/openbmc_project/Common/error.hpp" 1718e99992SDhruvaraj Subhashchandran 1898a23840SMatthew Barth extern int updateSensorRecordFromSSRAESC(const void *); 19d700e76aSTom extern sd_bus *bus; 20be703f71STom Joseph extern const ipmi::sensor::IdInfoMap sensors; 21be703f71STom Joseph using namespace phosphor::logging; 2218e99992SDhruvaraj Subhashchandran using InternalFailure = 2318e99992SDhruvaraj Subhashchandran sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 2498a23840SMatthew Barth 2598a23840SMatthew Barth void register_netfn_sen_functions() __attribute__((constructor)); 2698a23840SMatthew Barth 2798a23840SMatthew Barth struct sensorTypemap_t { 2898a23840SMatthew Barth uint8_t number; 2998a23840SMatthew Barth uint8_t typecode; 3098a23840SMatthew Barth char dbusname[32]; 3198a23840SMatthew Barth } ; 3298a23840SMatthew Barth 3398a23840SMatthew Barth sensorTypemap_t g_SensorTypeMap[] = { 3498a23840SMatthew Barth 3598a23840SMatthew Barth {0x01, 0x6F, "Temp"}, 3698a23840SMatthew Barth {0x0C, 0x6F, "DIMM"}, 3798a23840SMatthew Barth {0x0C, 0x6F, "MEMORY_BUFFER"}, 3898a23840SMatthew Barth {0x07, 0x6F, "PROC"}, 3998a23840SMatthew Barth {0x07, 0x6F, "CORE"}, 4098a23840SMatthew Barth {0x07, 0x6F, "CPU"}, 4198a23840SMatthew Barth {0x0F, 0x6F, "BootProgress"}, 4298a23840SMatthew Barth {0xe9, 0x09, "OccStatus"}, // E9 is an internal mapping to handle sensor type code os 0x09 4398a23840SMatthew Barth {0xC3, 0x6F, "BootCount"}, 4498a23840SMatthew Barth {0x1F, 0x6F, "OperatingSystemStatus"}, 4598a23840SMatthew Barth {0x12, 0x6F, "SYSTEM_EVENT"}, 4698a23840SMatthew Barth {0xC7, 0x03, "SYSTEM"}, 4798a23840SMatthew Barth {0xC7, 0x03, "MAIN_PLANAR"}, 4898a23840SMatthew Barth {0xC2, 0x6F, "PowerCap"}, 49558184eaSTom Joseph {0x0b, 0xCA, "PowerSupplyRedundancy"}, 500661beb1SJayanth Othayoth {0xDA, 0x03, "TurboAllowed"}, 51558184eaSTom Joseph {0xD8, 0xC8, "PowerSupplyDerating"}, 5298a23840SMatthew Barth {0xFF, 0x00, ""}, 5398a23840SMatthew Barth }; 5498a23840SMatthew Barth 5598a23840SMatthew Barth 5698a23840SMatthew Barth struct sensor_data_t { 5798a23840SMatthew Barth uint8_t sennum; 5898a23840SMatthew Barth } __attribute__ ((packed)) ; 5998a23840SMatthew Barth 6098a23840SMatthew Barth struct sensorreadingresp_t { 6198a23840SMatthew Barth uint8_t value; 6298a23840SMatthew Barth uint8_t operation; 6398a23840SMatthew Barth uint8_t indication[2]; 6498a23840SMatthew Barth } __attribute__ ((packed)) ; 6598a23840SMatthew Barth 66d700e76aSTom // Use a lookup table to find the interface name of a specific sensor 67d700e76aSTom // This will be used until an alternative is found. this is the first 68d700e76aSTom // step for mapping IPMI 69d700e76aSTom int find_interface_property_fru_type(dbus_interface_t *interface, const char *property_name, char *property_value) { 70d700e76aSTom 71d700e76aSTom char *str1; 72d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 73d700e76aSTom sd_bus_message *reply = NULL, *m=NULL; 74d700e76aSTom 75d700e76aSTom 76d700e76aSTom int r; 77d700e76aSTom 78d700e76aSTom r = sd_bus_message_new_method_call(bus,&m,interface->bus,interface->path,"org.freedesktop.DBus.Properties","Get"); 79d700e76aSTom if (r < 0) { 80d700e76aSTom fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); 81d700e76aSTom fprintf(stderr,"Bus: %s Path: %s Interface: %s \n", 82d700e76aSTom interface->bus, interface->path, interface->interface); 83d700e76aSTom goto final; 84d700e76aSTom } 85d700e76aSTom 86d700e76aSTom r = sd_bus_message_append(m, "ss", "org.openbmc.InventoryItem", property_name); 87d700e76aSTom if (r < 0) { 88d700e76aSTom fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r)); 89d700e76aSTom fprintf(stderr,"Bus: %s Path: %s Interface: %s \n", 90d700e76aSTom interface->bus, interface->path, interface->interface); 91d700e76aSTom goto final; 92d700e76aSTom } 93d700e76aSTom 94d700e76aSTom r = sd_bus_call(bus, m, 0, &error, &reply); 95d700e76aSTom if (r < 0) { 96d700e76aSTom fprintf(stderr, "Failed to call the method: %s", strerror(-r)); 97d700e76aSTom goto final; 98d700e76aSTom } 99d700e76aSTom 100d700e76aSTom r = sd_bus_message_read(reply, "v", "s", &str1) ; 101d700e76aSTom if (r < 0) { 102d700e76aSTom fprintf(stderr, "Failed to get a response: %s", strerror(-r)); 103d700e76aSTom goto final; 104d700e76aSTom } 105d700e76aSTom 106d700e76aSTom strcpy(property_value, str1); 107d700e76aSTom 108d700e76aSTom final: 109d700e76aSTom 110d700e76aSTom sd_bus_error_free(&error); 111d700e76aSTom m = sd_bus_message_unref(m); 112d700e76aSTom reply = sd_bus_message_unref(reply); 113d700e76aSTom 114d700e76aSTom return r; 115d700e76aSTom } 116d700e76aSTom 1172ae09b9aSEmily Shaffer int get_bus_for_path(const char *path, char **busname) { 1182ae09b9aSEmily Shaffer return mapper_get_service(bus, path, busname); 1192ae09b9aSEmily Shaffer } 120d700e76aSTom 1212ae09b9aSEmily Shaffer int legacy_dbus_openbmc_path(const char *type, const uint8_t num, dbus_interface_t *interface) { 122d700e76aSTom char *busname = NULL; 123d700e76aSTom const char *iface = "org.openbmc.managers.System"; 124d700e76aSTom const char *objname = "/org/openbmc/managers/System"; 125d700e76aSTom char *str1 = NULL, *str2, *str3; 126d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 127d700e76aSTom sd_bus_message *reply = NULL; 128d700e76aSTom 129d700e76aSTom 130d700e76aSTom int r; 1312ae09b9aSEmily Shaffer r = get_bus_for_path(objname, &busname); 132d700e76aSTom if (r < 0) { 133819ddd42SBrad Bishop fprintf(stderr, "Failed to get %s busname: %s\n", 134819ddd42SBrad Bishop objname, strerror(-r)); 135d700e76aSTom goto final; 136d700e76aSTom } 137d700e76aSTom 138d700e76aSTom r = sd_bus_call_method(bus,busname,objname,iface, "getObjectFromByteId", 139d700e76aSTom &error, &reply, "sy", type, num); 140d700e76aSTom if (r < 0) { 141d700e76aSTom fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); 142d700e76aSTom goto final; 143d700e76aSTom } 144d700e76aSTom 145d700e76aSTom r = sd_bus_message_read(reply, "(ss)", &str2, &str3); 146d700e76aSTom if (r < 0) { 147d700e76aSTom fprintf(stderr, "Failed to get a response: %s", strerror(-r)); 148d700e76aSTom goto final; 149d700e76aSTom } 150d700e76aSTom 1512ae09b9aSEmily Shaffer r = get_bus_for_path(str2, &str1); 152d700e76aSTom if (r < 0) { 153819ddd42SBrad Bishop fprintf(stderr, "Failed to get %s busname: %s\n", 154819ddd42SBrad Bishop str2, strerror(-r)); 155d700e76aSTom goto final; 156d700e76aSTom } 157d700e76aSTom 158d700e76aSTom strncpy(interface->bus, str1, MAX_DBUS_PATH); 159d700e76aSTom strncpy(interface->path, str2, MAX_DBUS_PATH); 160d700e76aSTom strncpy(interface->interface, str3, MAX_DBUS_PATH); 161d700e76aSTom 162d700e76aSTom interface->sensornumber = num; 1637117441cSEmily Shaffer // Make sure we know that the type hasn't been set, as newer codebase will 1647117441cSEmily Shaffer // set it automatically from the YAML at this step. 1657117441cSEmily Shaffer interface->sensortype = 0; 166d700e76aSTom 167d700e76aSTom final: 168d700e76aSTom 169d700e76aSTom sd_bus_error_free(&error); 170d700e76aSTom reply = sd_bus_message_unref(reply); 171d700e76aSTom free(busname); 172d700e76aSTom free(str1); 173d700e76aSTom 174d700e76aSTom return r; 175d700e76aSTom } 176d700e76aSTom 1772ae09b9aSEmily Shaffer // Use a lookup table to find the interface name of a specific sensor 1782ae09b9aSEmily Shaffer // This will be used until an alternative is found. this is the first 1792ae09b9aSEmily Shaffer // step for mapping IPMI 1802ae09b9aSEmily Shaffer int find_openbmc_path(uint8_t num, dbus_interface_t *interface) { 1812ae09b9aSEmily Shaffer int rc; 1822ae09b9aSEmily Shaffer 1832ae09b9aSEmily Shaffer // When the sensor map does not contain the sensor requested, 1842ae09b9aSEmily Shaffer // fall back to the legacy DBus lookup (deprecated) 1852ae09b9aSEmily Shaffer const auto& sensor_it = sensors.find(num); 1862ae09b9aSEmily Shaffer if (sensor_it == sensors.end()) 1872ae09b9aSEmily Shaffer { 1882ae09b9aSEmily Shaffer return legacy_dbus_openbmc_path("SENSOR", num, interface); 1892ae09b9aSEmily Shaffer } 1902ae09b9aSEmily Shaffer 1912ae09b9aSEmily Shaffer const auto& info = sensor_it->second; 1922ae09b9aSEmily Shaffer 1938451edf5SPatrick Williams char* busname = nullptr; 1942ae09b9aSEmily Shaffer rc = get_bus_for_path(info.sensorPath.c_str(), &busname); 1952ae09b9aSEmily Shaffer if (rc < 0) { 1962ae09b9aSEmily Shaffer fprintf(stderr, "Failed to get %s busname: %s\n", 1972ae09b9aSEmily Shaffer info.sensorPath.c_str(), 1982ae09b9aSEmily Shaffer busname); 1992ae09b9aSEmily Shaffer goto final; 2002ae09b9aSEmily Shaffer } 2012ae09b9aSEmily Shaffer 2022ae09b9aSEmily Shaffer interface->sensortype = info.sensorType; 2032ae09b9aSEmily Shaffer strcpy(interface->bus, busname); 2042ae09b9aSEmily Shaffer strcpy(interface->path, info.sensorPath.c_str()); 2052ae09b9aSEmily Shaffer // Take the interface name from the beginning of the DbusInterfaceMap. This 2062ae09b9aSEmily Shaffer // works for the Value interface but may not suffice for more complex 2072ae09b9aSEmily Shaffer // sensors. 2082ae09b9aSEmily Shaffer // tracked https://github.com/openbmc/phosphor-host-ipmid/issues/103 2091bb0d387SDeepak Kodihalli strcpy(interface->interface, info.propertyInterfaces.begin()->first.c_str()); 2102ae09b9aSEmily Shaffer interface->sensornumber = num; 2112ae09b9aSEmily Shaffer 2122ae09b9aSEmily Shaffer final: 2132ae09b9aSEmily Shaffer free(busname); 2142ae09b9aSEmily Shaffer return rc; 2152ae09b9aSEmily Shaffer } 2162ae09b9aSEmily Shaffer 217d700e76aSTom 218d700e76aSTom ///////////////////////////////////////////////////////////////////// 219d700e76aSTom // 220d700e76aSTom // Routines used by ipmi commands wanting to interact on the dbus 221d700e76aSTom // 222d700e76aSTom ///////////////////////////////////////////////////////////////////// 223d700e76aSTom int set_sensor_dbus_state_s(uint8_t number, const char *method, const char *value) { 224d700e76aSTom 225d700e76aSTom 226d700e76aSTom dbus_interface_t a; 227d700e76aSTom int r; 228d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 229d700e76aSTom sd_bus_message *m=NULL; 230d700e76aSTom 231d700e76aSTom fprintf(ipmidbus, "Attempting to set a dbus Variant Sensor 0x%02x via %s with a value of %s\n", 232d700e76aSTom number, method, value); 233d700e76aSTom 2342ae09b9aSEmily Shaffer r = find_openbmc_path(number, &a); 235d700e76aSTom 236d700e76aSTom if (r < 0) { 237d700e76aSTom fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); 238d700e76aSTom return 0; 239d700e76aSTom } 240d700e76aSTom 241d700e76aSTom r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method); 242d700e76aSTom if (r < 0) { 243d700e76aSTom fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); 244d700e76aSTom goto final; 245d700e76aSTom } 246d700e76aSTom 247d700e76aSTom r = sd_bus_message_append(m, "v", "s", value); 248d700e76aSTom if (r < 0) { 249d700e76aSTom fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r)); 250d700e76aSTom goto final; 251d700e76aSTom } 252d700e76aSTom 253d700e76aSTom 254d700e76aSTom r = sd_bus_call(bus, m, 0, &error, NULL); 255d700e76aSTom if (r < 0) { 256d700e76aSTom fprintf(stderr, "Failed to call the method: %s", strerror(-r)); 257d700e76aSTom } 258d700e76aSTom 259d700e76aSTom final: 260d700e76aSTom sd_bus_error_free(&error); 261d700e76aSTom m = sd_bus_message_unref(m); 262d700e76aSTom 263d700e76aSTom return 0; 264d700e76aSTom } 265d700e76aSTom int set_sensor_dbus_state_y(uint8_t number, const char *method, const uint8_t value) { 266d700e76aSTom 267d700e76aSTom 268d700e76aSTom dbus_interface_t a; 269d700e76aSTom int r; 270d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 271d700e76aSTom sd_bus_message *m=NULL; 272d700e76aSTom 273d700e76aSTom fprintf(ipmidbus, "Attempting to set a dbus Variant Sensor 0x%02x via %s with a value of 0x%02x\n", 274d700e76aSTom number, method, value); 275d700e76aSTom 2762ae09b9aSEmily Shaffer r = find_openbmc_path(number, &a); 277d700e76aSTom 278d700e76aSTom if (r < 0) { 279d700e76aSTom fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); 280d700e76aSTom return 0; 281d700e76aSTom } 282d700e76aSTom 283d700e76aSTom r = sd_bus_message_new_method_call(bus,&m,a.bus,a.path,a.interface,method); 284d700e76aSTom if (r < 0) { 285d700e76aSTom fprintf(stderr, "Failed to create a method call: %s", strerror(-r)); 286d700e76aSTom goto final; 287d700e76aSTom } 288d700e76aSTom 289d700e76aSTom r = sd_bus_message_append(m, "v", "i", value); 290d700e76aSTom if (r < 0) { 291d700e76aSTom fprintf(stderr, "Failed to create a input parameter: %s", strerror(-r)); 292d700e76aSTom goto final; 293d700e76aSTom } 294d700e76aSTom 295d700e76aSTom 296d700e76aSTom r = sd_bus_call(bus, m, 0, &error, NULL); 297d700e76aSTom if (r < 0) { 298d700e76aSTom fprintf(stderr, "12 Failed to call the method: %s", strerror(-r)); 299d700e76aSTom } 300d700e76aSTom 301d700e76aSTom final: 302d700e76aSTom sd_bus_error_free(&error); 303d700e76aSTom m = sd_bus_message_unref(m); 304d700e76aSTom 305d700e76aSTom return 0; 306d700e76aSTom } 307d700e76aSTom 30898a23840SMatthew Barth uint8_t dbus_to_sensor_type(char *p) { 30998a23840SMatthew Barth 31098a23840SMatthew Barth sensorTypemap_t *s = g_SensorTypeMap; 31198a23840SMatthew Barth char r=0; 31298a23840SMatthew Barth while (s->number != 0xFF) { 31398a23840SMatthew Barth if (!strcmp(s->dbusname,p)) { 314558184eaSTom Joseph r = s->typecode; 31598a23840SMatthew Barth break; 31698a23840SMatthew Barth } 31798a23840SMatthew Barth s++; 31898a23840SMatthew Barth } 31998a23840SMatthew Barth 32098a23840SMatthew Barth if (s->number == 0xFF) 32198a23840SMatthew Barth printf("Failed to find Sensor Type %s\n", p); 32298a23840SMatthew Barth 32398a23840SMatthew Barth return r; 32498a23840SMatthew Barth } 32598a23840SMatthew Barth 32698a23840SMatthew Barth 32798a23840SMatthew Barth uint8_t dbus_to_sensor_type_from_dbus(dbus_interface_t *a) { 32898a23840SMatthew Barth char fru_type_name[64]; 32998a23840SMatthew Barth int r= 0; 33098a23840SMatthew Barth 33198a23840SMatthew Barth r = find_interface_property_fru_type(a, "fru_type", fru_type_name); 33298a23840SMatthew Barth if (r<0) { 33398a23840SMatthew Barth fprintf(stderr, "Failed to get a fru type: %s", strerror(-r)); 33498a23840SMatthew Barth return -1; 33598a23840SMatthew Barth } else { 33698a23840SMatthew Barth return dbus_to_sensor_type(fru_type_name); 33798a23840SMatthew Barth } 33898a23840SMatthew Barth } 33998a23840SMatthew Barth 340391f3303SEmily Shaffer uint8_t get_type_from_interface(dbus_interface_t dbus_if) { 34198a23840SMatthew Barth 34298a23840SMatthew Barth char *p; 34356003453SBrad Bishop uint8_t type; 34498a23840SMatthew Barth 34598a23840SMatthew Barth // This is where sensors that do not exist in dbus but do 34698a23840SMatthew Barth // exist in the host code stop. This should indicate it 34798a23840SMatthew Barth // is not a supported sensor 348391f3303SEmily Shaffer if (dbus_if.interface[0] == 0) { return 0;} 34998a23840SMatthew Barth 3507117441cSEmily Shaffer // Fetch type from interface itself. 3517117441cSEmily Shaffer if (dbus_if.sensortype != 0) 3527117441cSEmily Shaffer { 3537117441cSEmily Shaffer type = dbus_if.sensortype; 3547117441cSEmily Shaffer } 3557117441cSEmily Shaffer // Legacy codebase does not populate type during initial handling: 3567117441cSEmily Shaffer else if (strstr(dbus_if.interface, "InventoryItem")) { 35798a23840SMatthew Barth // InventoryItems are real frus. So need to get the 35898a23840SMatthew Barth // fru_type property 359391f3303SEmily Shaffer type = dbus_to_sensor_type_from_dbus(&dbus_if); 36098a23840SMatthew Barth } else { 36198a23840SMatthew Barth // Non InventoryItems 362391f3303SEmily Shaffer p = strrchr (dbus_if.path, '/'); 36356003453SBrad Bishop type = dbus_to_sensor_type(p+1); 36498a23840SMatthew Barth } 36598a23840SMatthew Barth 36656003453SBrad Bishop return type; 36798a23840SMatthew Barth } 36898a23840SMatthew Barth 369391f3303SEmily Shaffer // Replaces find_sensor 370391f3303SEmily Shaffer uint8_t find_type_for_sensor_number(uint8_t num) { 371391f3303SEmily Shaffer int r; 372391f3303SEmily Shaffer dbus_interface_t dbus_if; 3732ae09b9aSEmily Shaffer r = find_openbmc_path(num, &dbus_if); 374391f3303SEmily Shaffer if (r < 0) { 375391f3303SEmily Shaffer fprintf(stderr, "Could not find sensor %d\n", num); 376391f3303SEmily Shaffer return r; 377391f3303SEmily Shaffer } 378391f3303SEmily Shaffer return get_type_from_interface(dbus_if); 379391f3303SEmily Shaffer } 380391f3303SEmily Shaffer 38198a23840SMatthew Barth 38298a23840SMatthew Barth 38398a23840SMatthew Barth 38498a23840SMatthew Barth 38598a23840SMatthew Barth ipmi_ret_t ipmi_sen_get_sensor_type(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 38698a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 38798a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 38898a23840SMatthew Barth { 38998a23840SMatthew Barth sensor_data_t *reqptr = (sensor_data_t*)request; 39098a23840SMatthew Barth ipmi_ret_t rc = IPMI_CC_OK; 39198a23840SMatthew Barth 39298a23840SMatthew Barth printf("IPMI GET_SENSOR_TYPE [0x%02X]\n",reqptr->sennum); 39398a23840SMatthew Barth 39498a23840SMatthew Barth // TODO Not sure what the System-event-sensor is suppose to return 39598a23840SMatthew Barth // need to ask Hostboot team 39698a23840SMatthew Barth unsigned char buf[] = {0x00,0x6F}; 39798a23840SMatthew Barth 398391f3303SEmily Shaffer buf[0] = find_type_for_sensor_number(reqptr->sennum); 39998a23840SMatthew Barth 40098a23840SMatthew Barth // HACK UNTIL Dbus gets updated or we find a better way 40198a23840SMatthew Barth if (buf[0] == 0) { 40298a23840SMatthew Barth rc = IPMI_CC_SENSOR_INVALID; 40398a23840SMatthew Barth } 40498a23840SMatthew Barth 40598a23840SMatthew Barth 40698a23840SMatthew Barth *data_len = sizeof(buf); 40798a23840SMatthew Barth memcpy(response, &buf, *data_len); 40898a23840SMatthew Barth 40998a23840SMatthew Barth return rc; 41098a23840SMatthew Barth } 41198a23840SMatthew Barth 412cc941e15SEmily Shaffer const std::set<std::string> analogSensorInterfaces = 413cc941e15SEmily Shaffer { 414cc941e15SEmily Shaffer "xyz.openbmc_project.Sensor.Value", 415cc941e15SEmily Shaffer }; 416cc941e15SEmily Shaffer 417cc941e15SEmily Shaffer bool isAnalogSensor(const std::string& interface) 418cc941e15SEmily Shaffer { 419cc941e15SEmily Shaffer return (analogSensorInterfaces.count(interface)); 420cc941e15SEmily Shaffer } 421cc941e15SEmily Shaffer 422be703f71STom Joseph ipmi_ret_t setSensorReading(void *request) 423be703f71STom Joseph { 424816e92b5STom Joseph ipmi::sensor::SetSensorReadingReq cmdData = 425816e92b5STom Joseph *(static_cast<ipmi::sensor::SetSensorReadingReq *>(request)); 426be703f71STom Joseph 427be703f71STom Joseph // Check if the Sensor Number is present 428e0af7209SDhruvaraj Subhashchandran const auto iter = sensors.find(cmdData.number); 429be703f71STom Joseph if (iter == sensors.end()) 430be703f71STom Joseph { 431be703f71STom Joseph return IPMI_CC_SENSOR_INVALID; 432be703f71STom Joseph } 433be703f71STom Joseph 43418e99992SDhruvaraj Subhashchandran try 43518e99992SDhruvaraj Subhashchandran { 436e0af7209SDhruvaraj Subhashchandran return iter->second.updateFunc(cmdData, iter->second); 437be703f71STom Joseph } 43818e99992SDhruvaraj Subhashchandran catch (InternalFailure& e) 43918e99992SDhruvaraj Subhashchandran { 44018e99992SDhruvaraj Subhashchandran log<level::ERR>("Set sensor failed", 44118e99992SDhruvaraj Subhashchandran entry("SENSOR_NUM=%d", cmdData.number)); 44218e99992SDhruvaraj Subhashchandran commit<InternalFailure>(); 44318e99992SDhruvaraj Subhashchandran } 4448202432fSTom Joseph catch (const std::runtime_error& e) 4458202432fSTom Joseph { 4468202432fSTom Joseph log<level::ERR>(e.what()); 4478202432fSTom Joseph } 44818e99992SDhruvaraj Subhashchandran 44918e99992SDhruvaraj Subhashchandran return IPMI_CC_UNSPECIFIED_ERROR; 45018e99992SDhruvaraj Subhashchandran } 45198a23840SMatthew Barth 45298a23840SMatthew Barth ipmi_ret_t ipmi_sen_set_sensor(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 45398a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 45498a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 45598a23840SMatthew Barth { 45698a23840SMatthew Barth sensor_data_t *reqptr = (sensor_data_t*)request; 45798a23840SMatthew Barth 45898a23840SMatthew Barth printf("IPMI SET_SENSOR [0x%02x]\n",reqptr->sennum); 45998a23840SMatthew Barth 460be703f71STom Joseph /* 461be703f71STom Joseph * This would support the Set Sensor Reading command for the presence 462be703f71STom Joseph * and functional state of Processor, Core & DIMM. For the remaining 463be703f71STom Joseph * sensors the existing support is invoked. 464be703f71STom Joseph */ 465be703f71STom Joseph auto ipmiRC = setSensorReading(request); 466be703f71STom Joseph 467be703f71STom Joseph if(ipmiRC == IPMI_CC_SENSOR_INVALID) 468be703f71STom Joseph { 46998a23840SMatthew Barth updateSensorRecordFromSSRAESC(reqptr); 470be703f71STom Joseph ipmiRC = IPMI_CC_OK; 471be703f71STom Joseph } 47298a23840SMatthew Barth 47398a23840SMatthew Barth *data_len=0; 474be703f71STom Joseph return ipmiRC; 47598a23840SMatthew Barth } 47698a23840SMatthew Barth 47798a23840SMatthew Barth 47898a23840SMatthew Barth ipmi_ret_t ipmi_sen_get_sensor_reading(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 47998a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 48098a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 48198a23840SMatthew Barth { 48298a23840SMatthew Barth sensor_data_t *reqptr = (sensor_data_t*)request; 48398a23840SMatthew Barth ipmi_ret_t rc = IPMI_CC_SENSOR_INVALID; 48440c35b1cSTom Joseph uint8_t type = 0; 48598a23840SMatthew Barth sensorreadingresp_t *resp = (sensorreadingresp_t*) response; 48698a23840SMatthew Barth int r; 48798a23840SMatthew Barth dbus_interface_t a; 48898a23840SMatthew Barth sd_bus *bus = ipmid_get_sd_bus_connection(); 48998a23840SMatthew Barth sd_bus_message *reply = NULL; 49098a23840SMatthew Barth int reading = 0; 4916244f93dSDhruvaraj Subhashchandran char* assertion = NULL; 492*c6162fb6STom Joseph ipmi::sensor::GetSensorResponse getResponse {}; 493*c6162fb6STom Joseph static constexpr auto scanningEnabledBit = 6; 49498a23840SMatthew Barth 49598a23840SMatthew Barth printf("IPMI GET_SENSOR_READING [0x%02x]\n",reqptr->sennum); 49698a23840SMatthew Barth 4972ae09b9aSEmily Shaffer r = find_openbmc_path(reqptr->sennum, &a); 49898a23840SMatthew Barth 49940c35b1cSTom Joseph if (r < 0) 50040c35b1cSTom Joseph { 50198a23840SMatthew Barth fprintf(stderr, "Failed to find Sensor 0x%02x\n", reqptr->sennum); 50298a23840SMatthew Barth } 50340c35b1cSTom Joseph else 50440c35b1cSTom Joseph { 505391f3303SEmily Shaffer type = get_type_from_interface(a); 50656003453SBrad Bishop if(type == 0) { 50756003453SBrad Bishop fprintf(stderr, "Failed to find Sensor 0x%02x\n", reqptr->sennum); 50856003453SBrad Bishop return IPMI_CC_SENSOR_INVALID; 50956003453SBrad Bishop } 51098a23840SMatthew Barth 51140c35b1cSTom Joseph fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", a.bus, a.path, 51240c35b1cSTom Joseph a.interface); 51340c35b1cSTom Joseph } 51498a23840SMatthew Barth 51598a23840SMatthew Barth *data_len=0; 51698a23840SMatthew Barth 51710f4959aSEmily Shaffer int64_t raw_value; 5181fabf229SEmily Shaffer ipmi::sensor::Info sensor; 5191fabf229SEmily Shaffer 52098a23840SMatthew Barth switch(type) { 52198a23840SMatthew Barth case 0xC2: 522d12ae758SDhruvaraj Subhashchandran case 0xC8: 52398a23840SMatthew Barth r = sd_bus_get_property(bus,a.bus, a.path, a.interface, "value", NULL, &reply, "i"); 52498a23840SMatthew Barth if (r < 0) { 52598a23840SMatthew Barth fprintf(stderr, "Failed to call sd_bus_get_property:%d, %s\n", r, strerror(-r)); 52698a23840SMatthew Barth fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", 52798a23840SMatthew Barth a.bus, a.path, a.interface); 52898a23840SMatthew Barth break; 52998a23840SMatthew Barth } 53098a23840SMatthew Barth 53198a23840SMatthew Barth r = sd_bus_message_read(reply, "i", &reading); 53298a23840SMatthew Barth if (r < 0) { 53398a23840SMatthew Barth fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r)); 53498a23840SMatthew Barth break; 53598a23840SMatthew Barth } 53698a23840SMatthew Barth 53798a23840SMatthew Barth printf("Contents of a 0x%02x is 0x%02x\n", type, reading); 53898a23840SMatthew Barth 53998a23840SMatthew Barth rc = IPMI_CC_OK; 54098a23840SMatthew Barth *data_len=sizeof(sensorreadingresp_t); 54198a23840SMatthew Barth 54298a23840SMatthew Barth resp->value = (uint8_t)reading; 54398a23840SMatthew Barth resp->operation = 0; 54498a23840SMatthew Barth resp->indication[0] = 0; 54598a23840SMatthew Barth resp->indication[1] = 0; 54698a23840SMatthew Barth break; 54798a23840SMatthew Barth 5486244f93dSDhruvaraj Subhashchandran //TODO openbmc/openbmc#2154 Move this sensor to right place. 5496244f93dSDhruvaraj Subhashchandran case 0xCA: 5506244f93dSDhruvaraj Subhashchandran r = sd_bus_get_property(bus,a.bus, a.path, a.interface, "value", NULL, &reply, "s"); 5516244f93dSDhruvaraj Subhashchandran if (r < 0) { 5526244f93dSDhruvaraj Subhashchandran fprintf(stderr, "Failed to call sd_bus_get_property:%d, %s\n", r, strerror(-r)); 5536244f93dSDhruvaraj Subhashchandran fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", 5546244f93dSDhruvaraj Subhashchandran a.bus, a.path, a.interface); 5556244f93dSDhruvaraj Subhashchandran break; 5566244f93dSDhruvaraj Subhashchandran } 5576244f93dSDhruvaraj Subhashchandran 5586244f93dSDhruvaraj Subhashchandran r = sd_bus_message_read(reply, "s", &assertion); 5596244f93dSDhruvaraj Subhashchandran if (r < 0) { 5606244f93dSDhruvaraj Subhashchandran fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r)); 5616244f93dSDhruvaraj Subhashchandran break; 5626244f93dSDhruvaraj Subhashchandran } 5636244f93dSDhruvaraj Subhashchandran 5646244f93dSDhruvaraj Subhashchandran rc = IPMI_CC_OK; 5656244f93dSDhruvaraj Subhashchandran *data_len=sizeof(sensorreadingresp_t); 5666244f93dSDhruvaraj Subhashchandran 5676244f93dSDhruvaraj Subhashchandran resp->value = 0; 5686244f93dSDhruvaraj Subhashchandran resp->operation = 0; 5696244f93dSDhruvaraj Subhashchandran if (strcmp(assertion,"Enabled") == 0) 5706244f93dSDhruvaraj Subhashchandran { 5716244f93dSDhruvaraj Subhashchandran resp->indication[0] = 0x02; 5726244f93dSDhruvaraj Subhashchandran } 5736244f93dSDhruvaraj Subhashchandran else 5746244f93dSDhruvaraj Subhashchandran { 5756244f93dSDhruvaraj Subhashchandran resp->indication[0] = 0x1; 5766244f93dSDhruvaraj Subhashchandran } 5776244f93dSDhruvaraj Subhashchandran resp->indication[1] = 0; 5786244f93dSDhruvaraj Subhashchandran break; 5796244f93dSDhruvaraj Subhashchandran 5801fabf229SEmily Shaffer case IPMI_SENSOR_TEMP: 5811fabf229SEmily Shaffer case IPMI_SENSOR_VOLTAGE: 5821fabf229SEmily Shaffer case IPMI_SENSOR_CURRENT: 5831fabf229SEmily Shaffer case IPMI_SENSOR_FAN: 5841fabf229SEmily Shaffer // Get reading for /xyz/openbmc_project/Sensor/Value.interface 58510f4959aSEmily Shaffer if(sensors.find(reqptr->sennum) == sensors.end()) 58610f4959aSEmily Shaffer { 58710f4959aSEmily Shaffer fprintf(stderr, "Failed to find config entry for Sensor 0x%02x\n", 58810f4959aSEmily Shaffer reqptr->sennum); 58910f4959aSEmily Shaffer return IPMI_CC_SENSOR_INVALID; 59010f4959aSEmily Shaffer } 59110f4959aSEmily Shaffer 59210f4959aSEmily Shaffer sensor = sensors.at(reqptr->sennum); 593cc941e15SEmily Shaffer if (ipmi::sensor::Mutability::Read != 594cc941e15SEmily Shaffer (sensor.mutability & ipmi::sensor::Mutability::Read)) 595cc941e15SEmily Shaffer { 596cc941e15SEmily Shaffer log<level::ERR>("Sensor was not readable.\n"); 597cc941e15SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 598cc941e15SEmily Shaffer } 599cc941e15SEmily Shaffer 6001fabf229SEmily Shaffer 6011fabf229SEmily Shaffer // Get value 6021fabf229SEmily Shaffer r = sd_bus_get_property_trivial(bus, 6031fabf229SEmily Shaffer a.bus, 6041fabf229SEmily Shaffer a.path, 6051fabf229SEmily Shaffer a.interface, 6061fabf229SEmily Shaffer "Value", 6071fabf229SEmily Shaffer NULL, 6081fabf229SEmily Shaffer 'x', 6091fabf229SEmily Shaffer &raw_value); 6101fabf229SEmily Shaffer if (r < 0) { 6111fabf229SEmily Shaffer fprintf(stderr, 6121fabf229SEmily Shaffer "Failed to call sd_bus_get_property:%d, %s, 'value'\n", 6131fabf229SEmily Shaffer r, 6141fabf229SEmily Shaffer strerror(-r)); 6151fabf229SEmily Shaffer fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", 6161fabf229SEmily Shaffer a.bus, a.path, a.interface); 6171fabf229SEmily Shaffer break; 6181fabf229SEmily Shaffer } 6191fabf229SEmily Shaffer 62010f4959aSEmily Shaffer // Prevent div0 62110f4959aSEmily Shaffer if (sensor.coefficientM == 0) { 62210f4959aSEmily Shaffer sensor.coefficientM = 1; 62310f4959aSEmily Shaffer }; 6241fabf229SEmily Shaffer 62510f4959aSEmily Shaffer resp->value = static_cast<uint8_t>( 62610f4959aSEmily Shaffer (raw_value - sensor.scaledOffset) / sensor.coefficientM); 627*c6162fb6STom Joseph resp->operation = 1 << scanningEnabledBit; // scanning enabled 628bbef71c2SEmily Shaffer resp->indication[0] = 0; // not a threshold sensor. ignore 6291fabf229SEmily Shaffer resp->indication[1] = 0; 6301fabf229SEmily Shaffer rc = IPMI_CC_OK; 6311fabf229SEmily Shaffer *data_len=sizeof(sensorreadingresp_t); 6321fabf229SEmily Shaffer break; 63398a23840SMatthew Barth default: 63414c15467STom Joseph { 63514c15467STom Joseph const auto iter = sensors.find(reqptr->sennum); 63614c15467STom Joseph if (iter == sensors.end()) 63714c15467STom Joseph { 63814c15467STom Joseph return IPMI_CC_SENSOR_INVALID; 63914c15467STom Joseph } 64014c15467STom Joseph 64114c15467STom Joseph try 64214c15467STom Joseph { 643*c6162fb6STom Joseph getResponse = iter->second.getFunc(iter->second); 64414c15467STom Joseph *data_len = getResponse.size(); 64514c15467STom Joseph memcpy(resp, getResponse.data(), *data_len); 646*c6162fb6STom Joseph resp->operation = 1 << scanningEnabledBit; 64714c15467STom Joseph return IPMI_CC_OK; 64814c15467STom Joseph } 64914c15467STom Joseph catch (InternalFailure& e) 65014c15467STom Joseph { 651*c6162fb6STom Joseph *data_len = getResponse.size(); 652*c6162fb6STom Joseph memcpy(resp, getResponse.data(), *data_len); 653*c6162fb6STom Joseph return IPMI_CC_OK; 65414c15467STom Joseph } 6558202432fSTom Joseph catch (const std::runtime_error& e) 6568202432fSTom Joseph { 657*c6162fb6STom Joseph *data_len = getResponse.size(); 658*c6162fb6STom Joseph memcpy(resp, getResponse.data(), *data_len); 659*c6162fb6STom Joseph return IPMI_CC_OK; 6608202432fSTom Joseph } 66114c15467STom Joseph } 66298a23840SMatthew Barth } 66398a23840SMatthew Barth 66498a23840SMatthew Barth reply = sd_bus_message_unref(reply); 66598a23840SMatthew Barth 66698a23840SMatthew Barth return rc; 66798a23840SMatthew Barth } 66898a23840SMatthew Barth 66998a23840SMatthew Barth ipmi_ret_t ipmi_sen_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 67098a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 67198a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 67298a23840SMatthew Barth { 67370aa8d96SNan Li ipmi_ret_t rc = IPMI_CC_INVALID; 67498a23840SMatthew Barth 67598a23840SMatthew Barth printf("IPMI S/E Wildcard Netfn:[0x%X], Cmd:[0x%X]\n",netfn,cmd); 67698a23840SMatthew Barth *data_len = 0; 67798a23840SMatthew Barth 67898a23840SMatthew Barth return rc; 67998a23840SMatthew Barth } 68098a23840SMatthew Barth 681d06e0e7eSEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 682d06e0e7eSEmily Shaffer ipmi_request_t request, 683d06e0e7eSEmily Shaffer ipmi_response_t response, 684d06e0e7eSEmily Shaffer ipmi_data_len_t data_len, 685d06e0e7eSEmily Shaffer ipmi_context_t context) 686d06e0e7eSEmily Shaffer { 687d06e0e7eSEmily Shaffer auto resp = static_cast<get_sdr_info::GetSdrInfoResp*>(response); 688d06e0e7eSEmily Shaffer if (request == nullptr || 689d06e0e7eSEmily Shaffer get_sdr_info::request::get_count(request) == false) 690d06e0e7eSEmily Shaffer { 691d06e0e7eSEmily Shaffer // Get Sensor Count 692d06e0e7eSEmily Shaffer resp->count = sensors.size(); 693d06e0e7eSEmily Shaffer } 694d06e0e7eSEmily Shaffer else 695d06e0e7eSEmily Shaffer { 696d06e0e7eSEmily Shaffer resp->count = 1; 697d06e0e7eSEmily Shaffer } 698d06e0e7eSEmily Shaffer 699d06e0e7eSEmily Shaffer // Multiple LUNs not supported. 700d06e0e7eSEmily Shaffer namespace response = get_sdr_info::response; 701d06e0e7eSEmily Shaffer response::set_lun_present(0, &(resp->luns_and_dynamic_population)); 702d06e0e7eSEmily Shaffer response::set_lun_not_present(1, &(resp->luns_and_dynamic_population)); 703d06e0e7eSEmily Shaffer response::set_lun_not_present(2, &(resp->luns_and_dynamic_population)); 704d06e0e7eSEmily Shaffer response::set_lun_not_present(3, &(resp->luns_and_dynamic_population)); 705d06e0e7eSEmily Shaffer response::set_static_population(&(resp->luns_and_dynamic_population)); 706d06e0e7eSEmily Shaffer 707d06e0e7eSEmily Shaffer *data_len = SDR_INFO_RESP_SIZE; 708d06e0e7eSEmily Shaffer 709d06e0e7eSEmily Shaffer return IPMI_CC_OK; 710d06e0e7eSEmily Shaffer } 711d06e0e7eSEmily Shaffer 712a344afc0SEmily Shaffer ipmi_ret_t ipmi_sen_reserve_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 713a344afc0SEmily Shaffer ipmi_request_t request, 714a344afc0SEmily Shaffer ipmi_response_t response, 715a344afc0SEmily Shaffer ipmi_data_len_t data_len, 716a344afc0SEmily Shaffer ipmi_context_t context) 717a344afc0SEmily Shaffer { 718a344afc0SEmily Shaffer // A constant reservation ID is okay until we implement add/remove SDR. 719a344afc0SEmily Shaffer const uint16_t reservation_id = 1; 720a344afc0SEmily Shaffer *(uint16_t*)response = reservation_id; 7215a5a6282SEmily Shaffer *data_len = sizeof(uint16_t); 722a344afc0SEmily Shaffer 723a344afc0SEmily Shaffer printf("Created new IPMI SDR reservation ID %d\n", *(uint16_t*)response); 724a344afc0SEmily Shaffer return IPMI_CC_OK; 725a344afc0SEmily Shaffer } 72698a23840SMatthew Barth 727cc941e15SEmily Shaffer void setUnitFieldsForObject(sd_bus *bus, 728cc941e15SEmily Shaffer const dbus_interface_t &iface, 729bbef71c2SEmily Shaffer const ipmi::sensor::Info *info, 730cc941e15SEmily Shaffer get_sdr::SensorDataFullRecordBody *body) 731bbef71c2SEmily Shaffer { 7321bb0d387SDeepak Kodihalli if (info->propertyInterfaces.begin()->first == 733bbef71c2SEmily Shaffer "xyz.openbmc_project.Sensor.Value") 734bbef71c2SEmily Shaffer { 735cc941e15SEmily Shaffer std::string result {}; 73662235618SEmily Shaffer if (info->unit.empty()) 73762235618SEmily Shaffer { 738cc941e15SEmily Shaffer char *raw_cstr = NULL; 739bbef71c2SEmily Shaffer if (0 > sd_bus_get_property_string(bus, iface.bus, iface.path, 740bbef71c2SEmily Shaffer iface.interface, "Unit", NULL, 741cc941e15SEmily Shaffer &raw_cstr)) 742cc941e15SEmily Shaffer { 743cc941e15SEmily Shaffer log<level::WARNING>("Unit interface missing.", 744e4050f29SGunnar Mills entry("BUS=%s", iface.bus), 745e4050f29SGunnar Mills entry("PATH=%s", iface.path)); 746bbef71c2SEmily Shaffer } 747cc941e15SEmily Shaffer else 748cc941e15SEmily Shaffer { 749cc941e15SEmily Shaffer result = raw_cstr; 750cc941e15SEmily Shaffer } 751cc941e15SEmily Shaffer free(raw_cstr); 75262235618SEmily Shaffer } 75362235618SEmily Shaffer else 75462235618SEmily Shaffer { 75562235618SEmily Shaffer result = info->unit; 75662235618SEmily Shaffer } 757bbef71c2SEmily Shaffer 758bbef71c2SEmily Shaffer namespace server = sdbusplus::xyz::openbmc_project::Sensor::server; 759cc941e15SEmily Shaffer try { 760cc941e15SEmily Shaffer auto unit = server::Value::convertUnitFromString(result); 761bbef71c2SEmily Shaffer // Unit strings defined in 762bbef71c2SEmily Shaffer // phosphor-dbus-interfaces/xyz/openbmc_project/Sensor/Value.interface.yaml 763bbef71c2SEmily Shaffer switch (unit) 764bbef71c2SEmily Shaffer { 765bbef71c2SEmily Shaffer case server::Value::Unit::DegreesC: 766bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_DEGREES_C; 767bbef71c2SEmily Shaffer break; 768bbef71c2SEmily Shaffer case server::Value::Unit::RPMS: 769bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_REVOLUTIONS; // revolutions 770bbef71c2SEmily Shaffer get_sdr::body::set_rate_unit(0b100, body); // per minute 771bbef71c2SEmily Shaffer break; 772bbef71c2SEmily Shaffer case server::Value::Unit::Volts: 773bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_VOLTS; 774bbef71c2SEmily Shaffer break; 775bbef71c2SEmily Shaffer case server::Value::Unit::Meters: 776bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_METERS; 777bbef71c2SEmily Shaffer break; 778bbef71c2SEmily Shaffer case server::Value::Unit::Amperes: 779bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_AMPERES; 780bbef71c2SEmily Shaffer break; 781bbef71c2SEmily Shaffer case server::Value::Unit::Joules: 782bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_JOULES; 783bbef71c2SEmily Shaffer break; 784bbef71c2SEmily Shaffer default: 785cc941e15SEmily Shaffer // Cannot be hit. 786cc941e15SEmily Shaffer fprintf(stderr, "Unknown value unit type: = %s\n", result.c_str()); 787cc941e15SEmily Shaffer } 788cc941e15SEmily Shaffer } 789cc941e15SEmily Shaffer catch (sdbusplus::exception::InvalidEnumString e) 790cc941e15SEmily Shaffer { 791cc941e15SEmily Shaffer log<level::WARNING>("Warning: no unit provided for sensor!"); 792cc941e15SEmily Shaffer } 793cc941e15SEmily Shaffer } 794bbef71c2SEmily Shaffer } 795bbef71c2SEmily Shaffer 796cc941e15SEmily Shaffer int64_t getScaleForObject(sd_bus *bus, 797cc941e15SEmily Shaffer const dbus_interface_t& iface, 798cc941e15SEmily Shaffer const ipmi::sensor::Info *info) 799cc941e15SEmily Shaffer { 800cc941e15SEmily Shaffer int64_t result = 0; 801cc941e15SEmily Shaffer if (info->propertyInterfaces.begin()->first == 802cc941e15SEmily Shaffer "xyz.openbmc_project.Sensor.Value") 803cc941e15SEmily Shaffer { 80462235618SEmily Shaffer if (info->hasScale) 80562235618SEmily Shaffer { 80662235618SEmily Shaffer result = info->scale; 80762235618SEmily Shaffer } 80862235618SEmily Shaffer else 80962235618SEmily Shaffer { 81010f4959aSEmily Shaffer if (0 > sd_bus_get_property_trivial(bus, 81110f4959aSEmily Shaffer iface.bus, 81210f4959aSEmily Shaffer iface.path, 81310f4959aSEmily Shaffer iface.interface, 81410f4959aSEmily Shaffer "Scale", 81510f4959aSEmily Shaffer NULL, 81610f4959aSEmily Shaffer 'x', 817cc941e15SEmily Shaffer &result)) { 818cc941e15SEmily Shaffer log<level::WARNING>("Scale interface missing.", 819e4050f29SGunnar Mills entry("BUS=%s", iface.bus), 820e4050f29SGunnar Mills entry("PATH=%s", iface.path)); 82110f4959aSEmily Shaffer } 822cc941e15SEmily Shaffer } 82362235618SEmily Shaffer } 824cc941e15SEmily Shaffer 825cc941e15SEmily Shaffer return result; 826cc941e15SEmily Shaffer } 827cc941e15SEmily Shaffer 828cc941e15SEmily Shaffer ipmi_ret_t populate_record_from_dbus(get_sdr::SensorDataFullRecordBody *body, 829cc941e15SEmily Shaffer const ipmi::sensor::Info *info, 830cc941e15SEmily Shaffer ipmi_data_len_t data_len) 831cc941e15SEmily Shaffer { 832cc941e15SEmily Shaffer /* Functional sensor case */ 833cc941e15SEmily Shaffer if (isAnalogSensor(info->propertyInterfaces.begin()->first)) 834cc941e15SEmily Shaffer { 835cc941e15SEmily Shaffer // Get bus 836cc941e15SEmily Shaffer sd_bus *bus = ipmid_get_sd_bus_connection(); 837cc941e15SEmily Shaffer dbus_interface_t iface; 838cc941e15SEmily Shaffer 839cc941e15SEmily Shaffer if (0 > find_openbmc_path(body->entity_id, &iface)) 840cc941e15SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 841cc941e15SEmily Shaffer 842cc941e15SEmily Shaffer body->sensor_units_1 = 0; // unsigned, no rate, no modifier, not a % 843cc941e15SEmily Shaffer 844cc941e15SEmily Shaffer /* Unit info */ 845cc941e15SEmily Shaffer setUnitFieldsForObject(bus, iface, info, body); 846cc941e15SEmily Shaffer 847cc941e15SEmily Shaffer /* Modifiers to reading info */ 848cc941e15SEmily Shaffer // Get scale 849cc941e15SEmily Shaffer int64_t scale = getScaleForObject(bus, iface, info); 85010f4959aSEmily Shaffer 85110f4959aSEmily Shaffer get_sdr::body::set_b(info->coefficientB, body); 85210f4959aSEmily Shaffer get_sdr::body::set_m(info->coefficientM, body); 85310f4959aSEmily Shaffer get_sdr::body::set_b_exp(info->exponentB, body); 85410f4959aSEmily Shaffer get_sdr::body::set_r_exp(scale, body); 855bbef71c2SEmily Shaffer 856bbef71c2SEmily Shaffer get_sdr::body::set_id_type(0b00, body); // 00 = unicode 8579642391dSTom Joseph } 8589642391dSTom Joseph 8599642391dSTom Joseph /* ID string */ 8609642391dSTom Joseph auto id_string = info->sensorNameFunc(*info); 8619642391dSTom Joseph 862bbef71c2SEmily Shaffer if (id_string.length() > FULL_RECORD_ID_STR_MAX_LENGTH) 863bbef71c2SEmily Shaffer { 864bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(FULL_RECORD_ID_STR_MAX_LENGTH, body); 865bbef71c2SEmily Shaffer } 866bbef71c2SEmily Shaffer else 867bbef71c2SEmily Shaffer { 868bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(id_string.length(), body); 869bbef71c2SEmily Shaffer } 870bbef71c2SEmily Shaffer strncpy(body->id_string, id_string.c_str(), 871bbef71c2SEmily Shaffer get_sdr::body::get_id_strlen(body)); 872bbef71c2SEmily Shaffer 873bbef71c2SEmily Shaffer return IPMI_CC_OK; 874bbef71c2SEmily Shaffer }; 875bbef71c2SEmily Shaffer 876bbef71c2SEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 877bbef71c2SEmily Shaffer ipmi_request_t request, ipmi_response_t response, 878bbef71c2SEmily Shaffer ipmi_data_len_t data_len, ipmi_context_t context) 879bbef71c2SEmily Shaffer { 880bbef71c2SEmily Shaffer ipmi_ret_t ret = IPMI_CC_OK; 881bbef71c2SEmily Shaffer get_sdr::GetSdrReq *req = (get_sdr::GetSdrReq*)request; 882bbef71c2SEmily Shaffer get_sdr::GetSdrResp *resp = (get_sdr::GetSdrResp*)response; 883bbef71c2SEmily Shaffer get_sdr::SensorDataFullRecord record = {0}; 884bbef71c2SEmily Shaffer if (req != NULL) 885bbef71c2SEmily Shaffer { 886bbef71c2SEmily Shaffer // Note: we use an iterator so we can provide the next ID at the end of 887bbef71c2SEmily Shaffer // the call. 888bbef71c2SEmily Shaffer auto sensor = sensors.begin(); 889bbef71c2SEmily Shaffer 890bbef71c2SEmily Shaffer // At the beginning of a scan, the host side will send us id=0. 891bbef71c2SEmily Shaffer if (get_sdr::request::get_record_id(req) != 0) 892bbef71c2SEmily Shaffer { 893bbef71c2SEmily Shaffer sensor = sensors.find(get_sdr::request::get_record_id(req)); 894bbef71c2SEmily Shaffer if(sensor == sensors.end()) { 895bbef71c2SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 896bbef71c2SEmily Shaffer } 897bbef71c2SEmily Shaffer } 898bbef71c2SEmily Shaffer 899bbef71c2SEmily Shaffer uint8_t sensor_id = sensor->first; 900bbef71c2SEmily Shaffer 901bbef71c2SEmily Shaffer /* Header */ 902bbef71c2SEmily Shaffer get_sdr::header::set_record_id(sensor_id, &(record.header)); 903bbef71c2SEmily Shaffer record.header.sdr_version = 0x51; // Based on IPMI Spec v2.0 rev 1.1 904bbef71c2SEmily Shaffer record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD; 905bbef71c2SEmily Shaffer record.header.record_length = sizeof(get_sdr::SensorDataFullRecord); 906bbef71c2SEmily Shaffer 907bbef71c2SEmily Shaffer /* Key */ 9089642391dSTom Joseph get_sdr::key::set_owner_id_bmc(&(record.key)); 909bbef71c2SEmily Shaffer record.key.sensor_number = sensor_id; 910bbef71c2SEmily Shaffer 911bbef71c2SEmily Shaffer /* Body */ 9129642391dSTom Joseph record.body.entity_id = sensor->second.entityType; 913bbef71c2SEmily Shaffer record.body.sensor_type = sensor->second.sensorType; 914bbef71c2SEmily Shaffer record.body.event_reading_type = sensor->second.sensorReadingType; 9159642391dSTom Joseph record.body.entity_instance = sensor->second.instance; 916bbef71c2SEmily Shaffer 917bbef71c2SEmily Shaffer // Set the type-specific details given the DBus interface 918bbef71c2SEmily Shaffer ret = populate_record_from_dbus(&(record.body), &(sensor->second), 919bbef71c2SEmily Shaffer data_len); 920bbef71c2SEmily Shaffer 921bbef71c2SEmily Shaffer if (++sensor == sensors.end()) 922bbef71c2SEmily Shaffer { 923bbef71c2SEmily Shaffer get_sdr::response::set_next_record_id(0xFFFF, resp); // last record 924bbef71c2SEmily Shaffer } 925bbef71c2SEmily Shaffer else 926bbef71c2SEmily Shaffer { 927bbef71c2SEmily Shaffer get_sdr::response::set_next_record_id(sensor->first, resp); 928bbef71c2SEmily Shaffer } 929bbef71c2SEmily Shaffer 930bbef71c2SEmily Shaffer *data_len = sizeof(get_sdr::GetSdrResp) - req->offset; 931bbef71c2SEmily Shaffer memcpy(resp->record_data, (char*)&record + req->offset, 932bbef71c2SEmily Shaffer sizeof(get_sdr::SensorDataFullRecord) - req->offset); 933bbef71c2SEmily Shaffer } 934bbef71c2SEmily Shaffer 935bbef71c2SEmily Shaffer return ret; 936bbef71c2SEmily Shaffer } 937bbef71c2SEmily Shaffer 938bbef71c2SEmily Shaffer 93998a23840SMatthew Barth void register_netfn_sen_functions() 94098a23840SMatthew Barth { 9410573237fSTom // <Wildcard Command> 942a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 943a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_WILDCARD); 944a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_WILDCARD, 945a344afc0SEmily Shaffer nullptr, ipmi_sen_wildcard, 9460573237fSTom PRIVILEGE_USER); 94798a23840SMatthew Barth 9480573237fSTom // <Get Sensor Type> 949a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 950a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE); 951a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE, 952a344afc0SEmily Shaffer nullptr, ipmi_sen_get_sensor_type, 9530573237fSTom PRIVILEGE_USER); 95498a23840SMatthew Barth 9550573237fSTom // <Set Sensor Reading and Event Status> 956a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 957a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_SET_SENSOR); 958a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_SET_SENSOR, 959a344afc0SEmily Shaffer nullptr, ipmi_sen_set_sensor, 9600573237fSTom PRIVILEGE_OPERATOR); 96198a23840SMatthew Barth 9620573237fSTom // <Get Sensor Reading> 963a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 964a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING); 965a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING, 966a344afc0SEmily Shaffer nullptr, ipmi_sen_get_sensor_reading, 967a344afc0SEmily Shaffer PRIVILEGE_USER); 968a344afc0SEmily Shaffer 969a344afc0SEmily Shaffer // <Reserve SDR> 970a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 971a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_RESERVE_SDR_REPO); 972a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_RESERVE_SDR_REPO, 973a344afc0SEmily Shaffer nullptr, ipmi_sen_reserve_sdr, 974a344afc0SEmily Shaffer PRIVILEGE_USER); 97598a23840SMatthew Barth 976d06e0e7eSEmily Shaffer // <Get SDR Info> 977a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%x]\n", 978a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SDR_INFO); 979a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SDR_INFO, 980a344afc0SEmily Shaffer nullptr, ipmi_sen_get_sdr_info, 981a344afc0SEmily Shaffer PRIVILEGE_USER); 982bbef71c2SEmily Shaffer 983bbef71c2SEmily Shaffer // <Get SDR> 984bbef71c2SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%x]\n", 985bbef71c2SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SDR); 986bbef71c2SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SDR, 987bbef71c2SEmily Shaffer nullptr, ipmi_sen_get_sdr, 988bbef71c2SEmily Shaffer PRIVILEGE_USER); 989bbef71c2SEmily Shaffer 99098a23840SMatthew Barth return; 99198a23840SMatthew Barth } 992