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 } 44418e99992SDhruvaraj Subhashchandran 44518e99992SDhruvaraj Subhashchandran return IPMI_CC_UNSPECIFIED_ERROR; 44618e99992SDhruvaraj Subhashchandran } 44798a23840SMatthew Barth 44898a23840SMatthew Barth ipmi_ret_t ipmi_sen_set_sensor(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 44998a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 45098a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 45198a23840SMatthew Barth { 45298a23840SMatthew Barth sensor_data_t *reqptr = (sensor_data_t*)request; 45398a23840SMatthew Barth 45498a23840SMatthew Barth printf("IPMI SET_SENSOR [0x%02x]\n",reqptr->sennum); 45598a23840SMatthew Barth 456be703f71STom Joseph /* 457be703f71STom Joseph * This would support the Set Sensor Reading command for the presence 458be703f71STom Joseph * and functional state of Processor, Core & DIMM. For the remaining 459be703f71STom Joseph * sensors the existing support is invoked. 460be703f71STom Joseph */ 461be703f71STom Joseph auto ipmiRC = setSensorReading(request); 462be703f71STom Joseph 463be703f71STom Joseph if(ipmiRC == IPMI_CC_SENSOR_INVALID) 464be703f71STom Joseph { 46598a23840SMatthew Barth updateSensorRecordFromSSRAESC(reqptr); 466be703f71STom Joseph ipmiRC = IPMI_CC_OK; 467be703f71STom Joseph } 46898a23840SMatthew Barth 46998a23840SMatthew Barth *data_len=0; 470be703f71STom Joseph return ipmiRC; 47198a23840SMatthew Barth } 47298a23840SMatthew Barth 47398a23840SMatthew Barth 47498a23840SMatthew Barth ipmi_ret_t ipmi_sen_get_sensor_reading(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 47598a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 47698a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 47798a23840SMatthew Barth { 47898a23840SMatthew Barth sensor_data_t *reqptr = (sensor_data_t*)request; 47998a23840SMatthew Barth ipmi_ret_t rc = IPMI_CC_SENSOR_INVALID; 48040c35b1cSTom Joseph uint8_t type = 0; 48198a23840SMatthew Barth sensorreadingresp_t *resp = (sensorreadingresp_t*) response; 48298a23840SMatthew Barth int r; 48398a23840SMatthew Barth dbus_interface_t a; 48498a23840SMatthew Barth sd_bus *bus = ipmid_get_sd_bus_connection(); 48598a23840SMatthew Barth sd_bus_message *reply = NULL; 48698a23840SMatthew Barth int reading = 0; 48798a23840SMatthew Barth 48898a23840SMatthew Barth printf("IPMI GET_SENSOR_READING [0x%02x]\n",reqptr->sennum); 48998a23840SMatthew Barth 4902ae09b9aSEmily Shaffer r = find_openbmc_path(reqptr->sennum, &a); 49198a23840SMatthew Barth 49240c35b1cSTom Joseph if (r < 0) 49340c35b1cSTom Joseph { 49498a23840SMatthew Barth fprintf(stderr, "Failed to find Sensor 0x%02x\n", reqptr->sennum); 49598a23840SMatthew Barth } 49640c35b1cSTom Joseph else 49740c35b1cSTom Joseph { 498391f3303SEmily Shaffer type = get_type_from_interface(a); 49956003453SBrad Bishop if(type == 0) { 50056003453SBrad Bishop fprintf(stderr, "Failed to find Sensor 0x%02x\n", reqptr->sennum); 50156003453SBrad Bishop return IPMI_CC_SENSOR_INVALID; 50256003453SBrad Bishop } 50398a23840SMatthew Barth 50440c35b1cSTom Joseph fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", a.bus, a.path, 50540c35b1cSTom Joseph a.interface); 50640c35b1cSTom Joseph } 50798a23840SMatthew Barth 50898a23840SMatthew Barth *data_len=0; 50998a23840SMatthew Barth 51010f4959aSEmily Shaffer int64_t raw_value; 5111fabf229SEmily Shaffer ipmi::sensor::Info sensor; 5121fabf229SEmily Shaffer 51398a23840SMatthew Barth switch(type) { 51498a23840SMatthew Barth case 0xC3: 51598a23840SMatthew Barth case 0xC2: 516558184eaSTom Joseph case 0xC8: 51798a23840SMatthew Barth r = sd_bus_get_property(bus,a.bus, a.path, a.interface, "value", NULL, &reply, "i"); 51898a23840SMatthew Barth if (r < 0) { 51998a23840SMatthew Barth fprintf(stderr, "Failed to call sd_bus_get_property:%d, %s\n", r, strerror(-r)); 52098a23840SMatthew Barth fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", 52198a23840SMatthew Barth a.bus, a.path, a.interface); 52298a23840SMatthew Barth break; 52398a23840SMatthew Barth } 52498a23840SMatthew Barth 52598a23840SMatthew Barth r = sd_bus_message_read(reply, "i", &reading); 52698a23840SMatthew Barth if (r < 0) { 52798a23840SMatthew Barth fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r)); 52898a23840SMatthew Barth break; 52998a23840SMatthew Barth } 53098a23840SMatthew Barth 53198a23840SMatthew Barth printf("Contents of a 0x%02x is 0x%02x\n", type, reading); 53298a23840SMatthew Barth 53398a23840SMatthew Barth rc = IPMI_CC_OK; 53498a23840SMatthew Barth *data_len=sizeof(sensorreadingresp_t); 53598a23840SMatthew Barth 53698a23840SMatthew Barth resp->value = (uint8_t)reading; 53798a23840SMatthew Barth resp->operation = 0; 53898a23840SMatthew Barth resp->indication[0] = 0; 53998a23840SMatthew Barth resp->indication[1] = 0; 54098a23840SMatthew Barth break; 54198a23840SMatthew Barth 5421fabf229SEmily Shaffer case IPMI_SENSOR_TEMP: 5431fabf229SEmily Shaffer case IPMI_SENSOR_VOLTAGE: 5441fabf229SEmily Shaffer case IPMI_SENSOR_CURRENT: 5451fabf229SEmily Shaffer case IPMI_SENSOR_FAN: 5461fabf229SEmily Shaffer // Get reading for /xyz/openbmc_project/Sensor/Value.interface 54710f4959aSEmily Shaffer if(sensors.find(reqptr->sennum) == sensors.end()) 54810f4959aSEmily Shaffer { 54910f4959aSEmily Shaffer fprintf(stderr, "Failed to find config entry for Sensor 0x%02x\n", 55010f4959aSEmily Shaffer reqptr->sennum); 55110f4959aSEmily Shaffer return IPMI_CC_SENSOR_INVALID; 55210f4959aSEmily Shaffer } 55310f4959aSEmily Shaffer 55410f4959aSEmily Shaffer sensor = sensors.at(reqptr->sennum); 555cc941e15SEmily Shaffer if (ipmi::sensor::Mutability::Read != 556cc941e15SEmily Shaffer (sensor.mutability & ipmi::sensor::Mutability::Read)) 557cc941e15SEmily Shaffer { 558cc941e15SEmily Shaffer log<level::ERR>("Sensor was not readable.\n"); 559cc941e15SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 560cc941e15SEmily Shaffer } 561cc941e15SEmily Shaffer 5621fabf229SEmily Shaffer 5631fabf229SEmily Shaffer // Get value 5641fabf229SEmily Shaffer r = sd_bus_get_property_trivial(bus, 5651fabf229SEmily Shaffer a.bus, 5661fabf229SEmily Shaffer a.path, 5671fabf229SEmily Shaffer a.interface, 5681fabf229SEmily Shaffer "Value", 5691fabf229SEmily Shaffer NULL, 5701fabf229SEmily Shaffer 'x', 5711fabf229SEmily Shaffer &raw_value); 5721fabf229SEmily Shaffer if (r < 0) { 5731fabf229SEmily Shaffer fprintf(stderr, 5741fabf229SEmily Shaffer "Failed to call sd_bus_get_property:%d, %s, 'value'\n", 5751fabf229SEmily Shaffer r, 5761fabf229SEmily Shaffer strerror(-r)); 5771fabf229SEmily Shaffer fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", 5781fabf229SEmily Shaffer a.bus, a.path, a.interface); 5791fabf229SEmily Shaffer break; 5801fabf229SEmily Shaffer } 5811fabf229SEmily Shaffer 58210f4959aSEmily Shaffer // Prevent div0 58310f4959aSEmily Shaffer if (sensor.coefficientM == 0) { 58410f4959aSEmily Shaffer sensor.coefficientM = 1; 58510f4959aSEmily Shaffer }; 5861fabf229SEmily Shaffer 58710f4959aSEmily Shaffer resp->value = static_cast<uint8_t>( 58810f4959aSEmily Shaffer (raw_value - sensor.scaledOffset) / sensor.coefficientM); 589bbef71c2SEmily Shaffer resp->operation = 1<<6; // scanning enabled 590bbef71c2SEmily Shaffer resp->indication[0] = 0; // not a threshold sensor. ignore 5911fabf229SEmily Shaffer resp->indication[1] = 0; 5921fabf229SEmily Shaffer rc = IPMI_CC_OK; 5931fabf229SEmily Shaffer *data_len=sizeof(sensorreadingresp_t); 5941fabf229SEmily Shaffer break; 59560cac721STom Joseph case IPMI_SENSOR_TPM: 59660cac721STom Joseph { 59760cac721STom Joseph auto iter = sensors.find(reqptr->sennum); 59860cac721STom Joseph if (iter == sensors.end()) 59960cac721STom Joseph { 60060cac721STom Joseph return IPMI_CC_SENSOR_INVALID; 60160cac721STom Joseph } 6021fabf229SEmily Shaffer 60360cac721STom Joseph auto& interfaceList = iter->second.propertyInterfaces; 60460cac721STom Joseph if (interfaceList.empty()) 60560cac721STom Joseph { 60660cac721STom Joseph log<level::ERR>("Interface List empty for the sensor", 60760cac721STom Joseph entry("SENSOR_NUMBER=%d", reqptr->sennum)); 60860cac721STom Joseph return IPMI_CC_UNSPECIFIED_ERROR; 60960cac721STom Joseph } 61060cac721STom Joseph 61160cac721STom Joseph /* For the TPM sensor there is no reading value and sensor scanning 61260cac721STom Joseph * is disabled. This is a discrete sensor and only the 61360cac721STom Joseph * corresponding state is asserted. 61460cac721STom Joseph */ 61560cac721STom Joseph resp->value = 0; 61660cac721STom Joseph resp->operation = 0; 61760cac721STom Joseph resp->indication[0] = 0; 61860cac721STom Joseph resp->indication[1] = 0; 61960cac721STom Joseph 62060cac721STom Joseph try 62160cac721STom Joseph { 62260cac721STom Joseph for (const auto& interface : interfaceList) 62360cac721STom Joseph { 62460cac721STom Joseph for (const auto& property : interface.second) 62560cac721STom Joseph { 62660cac721STom Joseph sdbusplus::bus::bus dbus{ipmid_get_sd_bus_connection()}; 62760cac721STom Joseph 62860cac721STom Joseph auto service = ipmi::getService( 62960cac721STom Joseph dbus, 63060cac721STom Joseph interface.first, 63160cac721STom Joseph iter->second.sensorPath); 63260cac721STom Joseph 63360cac721STom Joseph auto propValue = ipmi::getDbusProperty( 63460cac721STom Joseph dbus, service, iter->second.sensorPath, 63560cac721STom Joseph interface.first, property.first); 63660cac721STom Joseph 63760cac721STom Joseph auto tpmStatus = propValue.get<bool>(); 63860cac721STom Joseph 63960cac721STom Joseph for (const auto& value : property.second) 64060cac721STom Joseph { 64160cac721STom Joseph if (tpmStatus == (value.second.assert).get<bool>()) 64260cac721STom Joseph { 64360cac721STom Joseph /* 64460cac721STom Joseph * The discrete sensors support upto 14 states. 64560cac721STom Joseph * The assertion states for discrete sensors are 64660cac721STom Joseph * stored in 2 bytes, 0-7 in Byte 4 of the 64760cac721STom Joseph * response and 8-14 in Byte 5 of the response. 64860cac721STom Joseph */ 64960cac721STom Joseph resp->indication[0] |= 1 << (value.first); 65060cac721STom Joseph break; 65160cac721STom Joseph } 65260cac721STom Joseph } 65360cac721STom Joseph } 65460cac721STom Joseph } 65560cac721STom Joseph 65660cac721STom Joseph rc = IPMI_CC_OK; 65760cac721STom Joseph *data_len = sizeof(sensorreadingresp_t); 65860cac721STom Joseph } 65960cac721STom Joseph catch (InternalFailure& e) 66060cac721STom Joseph { 66160cac721STom Joseph return IPMI_CC_UNSPECIFIED_ERROR; 66260cac721STom Joseph } 66360cac721STom Joseph break; 66460cac721STom Joseph } 66598a23840SMatthew Barth default: 666*14c15467STom Joseph { 667*14c15467STom Joseph const auto iter = sensors.find(reqptr->sennum); 668*14c15467STom Joseph if (iter == sensors.end()) 669*14c15467STom Joseph { 670*14c15467STom Joseph return IPMI_CC_SENSOR_INVALID; 671*14c15467STom Joseph } 672*14c15467STom Joseph 673*14c15467STom Joseph try 674*14c15467STom Joseph { 675*14c15467STom Joseph auto getResponse = iter->second.getFunc(iter->second); 676*14c15467STom Joseph *data_len = getResponse.size(); 677*14c15467STom Joseph memcpy(resp, getResponse.data(), *data_len); 678*14c15467STom Joseph return IPMI_CC_OK; 679*14c15467STom Joseph } 680*14c15467STom Joseph catch (InternalFailure& e) 681*14c15467STom Joseph { 682*14c15467STom Joseph log<level::ERR>("Get sensor failed", 683*14c15467STom Joseph entry("SENSOR_NUM=%d", reqptr->sennum)); 684*14c15467STom Joseph commit<InternalFailure>(); 685*14c15467STom Joseph return IPMI_CC_SENSOR_INVALID; 686*14c15467STom Joseph } 687*14c15467STom Joseph } 68898a23840SMatthew Barth } 68998a23840SMatthew Barth 69098a23840SMatthew Barth reply = sd_bus_message_unref(reply); 69198a23840SMatthew Barth 69298a23840SMatthew Barth return rc; 69398a23840SMatthew Barth } 69498a23840SMatthew Barth 69598a23840SMatthew Barth ipmi_ret_t ipmi_sen_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 69698a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 69798a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 69898a23840SMatthew Barth { 69970aa8d96SNan Li ipmi_ret_t rc = IPMI_CC_INVALID; 70098a23840SMatthew Barth 70198a23840SMatthew Barth printf("IPMI S/E Wildcard Netfn:[0x%X], Cmd:[0x%X]\n",netfn,cmd); 70298a23840SMatthew Barth *data_len = 0; 70398a23840SMatthew Barth 70498a23840SMatthew Barth return rc; 70598a23840SMatthew Barth } 70698a23840SMatthew Barth 707d06e0e7eSEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 708d06e0e7eSEmily Shaffer ipmi_request_t request, 709d06e0e7eSEmily Shaffer ipmi_response_t response, 710d06e0e7eSEmily Shaffer ipmi_data_len_t data_len, 711d06e0e7eSEmily Shaffer ipmi_context_t context) 712d06e0e7eSEmily Shaffer { 713d06e0e7eSEmily Shaffer auto resp = static_cast<get_sdr_info::GetSdrInfoResp*>(response); 714d06e0e7eSEmily Shaffer if (request == nullptr || 715d06e0e7eSEmily Shaffer get_sdr_info::request::get_count(request) == false) 716d06e0e7eSEmily Shaffer { 717d06e0e7eSEmily Shaffer // Get Sensor Count 718d06e0e7eSEmily Shaffer resp->count = sensors.size(); 719d06e0e7eSEmily Shaffer } 720d06e0e7eSEmily Shaffer else 721d06e0e7eSEmily Shaffer { 722d06e0e7eSEmily Shaffer resp->count = 1; 723d06e0e7eSEmily Shaffer } 724d06e0e7eSEmily Shaffer 725d06e0e7eSEmily Shaffer // Multiple LUNs not supported. 726d06e0e7eSEmily Shaffer namespace response = get_sdr_info::response; 727d06e0e7eSEmily Shaffer response::set_lun_present(0, &(resp->luns_and_dynamic_population)); 728d06e0e7eSEmily Shaffer response::set_lun_not_present(1, &(resp->luns_and_dynamic_population)); 729d06e0e7eSEmily Shaffer response::set_lun_not_present(2, &(resp->luns_and_dynamic_population)); 730d06e0e7eSEmily Shaffer response::set_lun_not_present(3, &(resp->luns_and_dynamic_population)); 731d06e0e7eSEmily Shaffer response::set_static_population(&(resp->luns_and_dynamic_population)); 732d06e0e7eSEmily Shaffer 733d06e0e7eSEmily Shaffer *data_len = SDR_INFO_RESP_SIZE; 734d06e0e7eSEmily Shaffer 735d06e0e7eSEmily Shaffer return IPMI_CC_OK; 736d06e0e7eSEmily Shaffer } 737d06e0e7eSEmily Shaffer 738a344afc0SEmily Shaffer ipmi_ret_t ipmi_sen_reserve_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 739a344afc0SEmily Shaffer ipmi_request_t request, 740a344afc0SEmily Shaffer ipmi_response_t response, 741a344afc0SEmily Shaffer ipmi_data_len_t data_len, 742a344afc0SEmily Shaffer ipmi_context_t context) 743a344afc0SEmily Shaffer { 744a344afc0SEmily Shaffer // A constant reservation ID is okay until we implement add/remove SDR. 745a344afc0SEmily Shaffer const uint16_t reservation_id = 1; 746a344afc0SEmily Shaffer *(uint16_t*)response = reservation_id; 7475a5a6282SEmily Shaffer *data_len = sizeof(uint16_t); 748a344afc0SEmily Shaffer 749a344afc0SEmily Shaffer printf("Created new IPMI SDR reservation ID %d\n", *(uint16_t*)response); 750a344afc0SEmily Shaffer return IPMI_CC_OK; 751a344afc0SEmily Shaffer } 75298a23840SMatthew Barth 753cc941e15SEmily Shaffer void setUnitFieldsForObject(sd_bus *bus, 754cc941e15SEmily Shaffer const dbus_interface_t &iface, 755bbef71c2SEmily Shaffer const ipmi::sensor::Info *info, 756cc941e15SEmily Shaffer get_sdr::SensorDataFullRecordBody *body) 757bbef71c2SEmily Shaffer { 7581bb0d387SDeepak Kodihalli if (info->propertyInterfaces.begin()->first == 759bbef71c2SEmily Shaffer "xyz.openbmc_project.Sensor.Value") 760bbef71c2SEmily Shaffer { 761cc941e15SEmily Shaffer std::string result {}; 762cc941e15SEmily Shaffer char *raw_cstr = NULL; 763bbef71c2SEmily Shaffer if (0 > sd_bus_get_property_string(bus, iface.bus, iface.path, 764bbef71c2SEmily Shaffer iface.interface, "Unit", NULL, 765cc941e15SEmily Shaffer &raw_cstr)) 766cc941e15SEmily Shaffer { 767cc941e15SEmily Shaffer log<level::WARNING>("Unit interface missing.", 768cc941e15SEmily Shaffer entry("bus=%s, path=%s", iface.bus, iface.path)); 769bbef71c2SEmily Shaffer } 770cc941e15SEmily Shaffer else 771cc941e15SEmily Shaffer { 772cc941e15SEmily Shaffer result = raw_cstr; 773cc941e15SEmily Shaffer } 774cc941e15SEmily Shaffer free(raw_cstr); 775bbef71c2SEmily Shaffer 776bbef71c2SEmily Shaffer namespace server = sdbusplus::xyz::openbmc_project::Sensor::server; 777cc941e15SEmily Shaffer try { 778cc941e15SEmily Shaffer auto unit = server::Value::convertUnitFromString(result); 779bbef71c2SEmily Shaffer // Unit strings defined in 780bbef71c2SEmily Shaffer // phosphor-dbus-interfaces/xyz/openbmc_project/Sensor/Value.interface.yaml 781bbef71c2SEmily Shaffer switch (unit) 782bbef71c2SEmily Shaffer { 783bbef71c2SEmily Shaffer case server::Value::Unit::DegreesC: 784bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_DEGREES_C; 785bbef71c2SEmily Shaffer break; 786bbef71c2SEmily Shaffer case server::Value::Unit::RPMS: 787bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_REVOLUTIONS; // revolutions 788bbef71c2SEmily Shaffer get_sdr::body::set_rate_unit(0b100, body); // per minute 789bbef71c2SEmily Shaffer break; 790bbef71c2SEmily Shaffer case server::Value::Unit::Volts: 791bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_VOLTS; 792bbef71c2SEmily Shaffer break; 793bbef71c2SEmily Shaffer case server::Value::Unit::Meters: 794bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_METERS; 795bbef71c2SEmily Shaffer break; 796bbef71c2SEmily Shaffer case server::Value::Unit::Amperes: 797bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_AMPERES; 798bbef71c2SEmily Shaffer break; 799bbef71c2SEmily Shaffer case server::Value::Unit::Joules: 800bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_JOULES; 801bbef71c2SEmily Shaffer break; 802bbef71c2SEmily Shaffer default: 803cc941e15SEmily Shaffer // Cannot be hit. 804cc941e15SEmily Shaffer fprintf(stderr, "Unknown value unit type: = %s\n", result.c_str()); 805cc941e15SEmily Shaffer } 806cc941e15SEmily Shaffer } 807cc941e15SEmily Shaffer catch (sdbusplus::exception::InvalidEnumString e) 808cc941e15SEmily Shaffer { 809cc941e15SEmily Shaffer log<level::WARNING>("Warning: no unit provided for sensor!"); 810cc941e15SEmily Shaffer } 811cc941e15SEmily Shaffer } 812bbef71c2SEmily Shaffer } 813bbef71c2SEmily Shaffer 814cc941e15SEmily Shaffer int64_t getScaleForObject(sd_bus *bus, 815cc941e15SEmily Shaffer const dbus_interface_t& iface, 816cc941e15SEmily Shaffer const ipmi::sensor::Info *info) 817cc941e15SEmily Shaffer { 818cc941e15SEmily Shaffer int64_t result = 0; 819cc941e15SEmily Shaffer if (info->propertyInterfaces.begin()->first == 820cc941e15SEmily Shaffer "xyz.openbmc_project.Sensor.Value") 821cc941e15SEmily Shaffer { 82210f4959aSEmily Shaffer if (0 > sd_bus_get_property_trivial(bus, 82310f4959aSEmily Shaffer iface.bus, 82410f4959aSEmily Shaffer iface.path, 82510f4959aSEmily Shaffer iface.interface, 82610f4959aSEmily Shaffer "Scale", 82710f4959aSEmily Shaffer NULL, 82810f4959aSEmily Shaffer 'x', 829cc941e15SEmily Shaffer &result)) { 830cc941e15SEmily Shaffer log<level::WARNING>("Scale interface missing.", 831cc941e15SEmily Shaffer entry("bus=%s, path=%s", iface.bus, iface.path)); 83210f4959aSEmily Shaffer } 833cc941e15SEmily Shaffer } 834cc941e15SEmily Shaffer 835cc941e15SEmily Shaffer return result; 836cc941e15SEmily Shaffer } 837cc941e15SEmily Shaffer 838cc941e15SEmily Shaffer ipmi_ret_t populate_record_from_dbus(get_sdr::SensorDataFullRecordBody *body, 839cc941e15SEmily Shaffer const ipmi::sensor::Info *info, 840cc941e15SEmily Shaffer ipmi_data_len_t data_len) 841cc941e15SEmily Shaffer { 842cc941e15SEmily Shaffer /* Functional sensor case */ 843cc941e15SEmily Shaffer if (isAnalogSensor(info->propertyInterfaces.begin()->first)) 844cc941e15SEmily Shaffer { 845cc941e15SEmily Shaffer // Get bus 846cc941e15SEmily Shaffer sd_bus *bus = ipmid_get_sd_bus_connection(); 847cc941e15SEmily Shaffer dbus_interface_t iface; 848cc941e15SEmily Shaffer 849cc941e15SEmily Shaffer if (0 > find_openbmc_path(body->entity_id, &iface)) 850cc941e15SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 851cc941e15SEmily Shaffer 852cc941e15SEmily Shaffer body->sensor_units_1 = 0; // unsigned, no rate, no modifier, not a % 853cc941e15SEmily Shaffer 854cc941e15SEmily Shaffer /* Unit info */ 855cc941e15SEmily Shaffer setUnitFieldsForObject(bus, iface, info, body); 856cc941e15SEmily Shaffer 857cc941e15SEmily Shaffer /* Modifiers to reading info */ 858cc941e15SEmily Shaffer // Get scale 859cc941e15SEmily Shaffer int64_t scale = getScaleForObject(bus, iface, info); 86010f4959aSEmily Shaffer 86110f4959aSEmily Shaffer get_sdr::body::set_b(info->coefficientB, body); 86210f4959aSEmily Shaffer get_sdr::body::set_m(info->coefficientM, body); 86310f4959aSEmily Shaffer get_sdr::body::set_b_exp(info->exponentB, body); 86410f4959aSEmily Shaffer get_sdr::body::set_r_exp(scale, body); 865bbef71c2SEmily Shaffer 866bbef71c2SEmily Shaffer /* ID string */ 867bbef71c2SEmily Shaffer std::string id_string = info->sensorPath.substr( 868bbef71c2SEmily Shaffer info->sensorPath.find_last_of('/')+1, info->sensorPath.length()); 869bbef71c2SEmily Shaffer get_sdr::body::set_id_type(0b00, body); // 00 = unicode 870bbef71c2SEmily Shaffer if (id_string.length() > FULL_RECORD_ID_STR_MAX_LENGTH) 871bbef71c2SEmily Shaffer { 872bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(FULL_RECORD_ID_STR_MAX_LENGTH, body); 873bbef71c2SEmily Shaffer } 874bbef71c2SEmily Shaffer else 875bbef71c2SEmily Shaffer { 876bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(id_string.length(), body); 877bbef71c2SEmily Shaffer } 878bbef71c2SEmily Shaffer strncpy(body->id_string, id_string.c_str(), 879bbef71c2SEmily Shaffer get_sdr::body::get_id_strlen(body)); 880bbef71c2SEmily Shaffer } 881bbef71c2SEmily Shaffer 882bbef71c2SEmily Shaffer return IPMI_CC_OK; 883bbef71c2SEmily Shaffer }; 884bbef71c2SEmily Shaffer 885bbef71c2SEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 886bbef71c2SEmily Shaffer ipmi_request_t request, ipmi_response_t response, 887bbef71c2SEmily Shaffer ipmi_data_len_t data_len, ipmi_context_t context) 888bbef71c2SEmily Shaffer { 889bbef71c2SEmily Shaffer ipmi_ret_t ret = IPMI_CC_OK; 890bbef71c2SEmily Shaffer get_sdr::GetSdrReq *req = (get_sdr::GetSdrReq*)request; 891bbef71c2SEmily Shaffer get_sdr::GetSdrResp *resp = (get_sdr::GetSdrResp*)response; 892bbef71c2SEmily Shaffer get_sdr::SensorDataFullRecord record = {0}; 893bbef71c2SEmily Shaffer if (req != NULL) 894bbef71c2SEmily Shaffer { 895bbef71c2SEmily Shaffer // Note: we use an iterator so we can provide the next ID at the end of 896bbef71c2SEmily Shaffer // the call. 897bbef71c2SEmily Shaffer auto sensor = sensors.begin(); 898bbef71c2SEmily Shaffer 899bbef71c2SEmily Shaffer // At the beginning of a scan, the host side will send us id=0. 900bbef71c2SEmily Shaffer if (get_sdr::request::get_record_id(req) != 0) 901bbef71c2SEmily Shaffer { 902bbef71c2SEmily Shaffer sensor = sensors.find(get_sdr::request::get_record_id(req)); 903bbef71c2SEmily Shaffer if(sensor == sensors.end()) { 904bbef71c2SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 905bbef71c2SEmily Shaffer } 906bbef71c2SEmily Shaffer } 907bbef71c2SEmily Shaffer 908bbef71c2SEmily Shaffer uint8_t sensor_id = sensor->first; 909bbef71c2SEmily Shaffer 910bbef71c2SEmily Shaffer /* Header */ 911bbef71c2SEmily Shaffer get_sdr::header::set_record_id(sensor_id, &(record.header)); 912bbef71c2SEmily Shaffer record.header.sdr_version = 0x51; // Based on IPMI Spec v2.0 rev 1.1 913bbef71c2SEmily Shaffer record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD; 914bbef71c2SEmily Shaffer record.header.record_length = sizeof(get_sdr::SensorDataFullRecord); 915bbef71c2SEmily Shaffer 916bbef71c2SEmily Shaffer /* Key */ 917bbef71c2SEmily Shaffer record.key.sensor_number = sensor_id; 918bbef71c2SEmily Shaffer 919bbef71c2SEmily Shaffer /* Body */ 920bbef71c2SEmily Shaffer record.body.entity_id = sensor_id; 921bbef71c2SEmily Shaffer record.body.sensor_type = sensor->second.sensorType; 922bbef71c2SEmily Shaffer record.body.event_reading_type = sensor->second.sensorReadingType; 923bbef71c2SEmily Shaffer 924bbef71c2SEmily Shaffer // Set the type-specific details given the DBus interface 925bbef71c2SEmily Shaffer ret = populate_record_from_dbus(&(record.body), &(sensor->second), 926bbef71c2SEmily Shaffer data_len); 927bbef71c2SEmily Shaffer 928bbef71c2SEmily Shaffer if (++sensor == sensors.end()) 929bbef71c2SEmily Shaffer { 930bbef71c2SEmily Shaffer get_sdr::response::set_next_record_id(0xFFFF, resp); // last record 931bbef71c2SEmily Shaffer } 932bbef71c2SEmily Shaffer else 933bbef71c2SEmily Shaffer { 934bbef71c2SEmily Shaffer get_sdr::response::set_next_record_id(sensor->first, resp); 935bbef71c2SEmily Shaffer } 936bbef71c2SEmily Shaffer 937bbef71c2SEmily Shaffer *data_len = sizeof(get_sdr::GetSdrResp) - req->offset; 938bbef71c2SEmily Shaffer memcpy(resp->record_data, (char*)&record + req->offset, 939bbef71c2SEmily Shaffer sizeof(get_sdr::SensorDataFullRecord) - req->offset); 940bbef71c2SEmily Shaffer } 941bbef71c2SEmily Shaffer 942bbef71c2SEmily Shaffer return ret; 943bbef71c2SEmily Shaffer } 944bbef71c2SEmily Shaffer 945bbef71c2SEmily Shaffer 94698a23840SMatthew Barth void register_netfn_sen_functions() 94798a23840SMatthew Barth { 9480573237fSTom // <Wildcard Command> 949a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 950a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_WILDCARD); 951a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_WILDCARD, 952a344afc0SEmily Shaffer nullptr, ipmi_sen_wildcard, 9530573237fSTom PRIVILEGE_USER); 95498a23840SMatthew Barth 9550573237fSTom // <Get Sensor Type> 956a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 957a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE); 958a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE, 959a344afc0SEmily Shaffer nullptr, ipmi_sen_get_sensor_type, 9600573237fSTom PRIVILEGE_USER); 96198a23840SMatthew Barth 9620573237fSTom // <Set Sensor Reading and Event Status> 963a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 964a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_SET_SENSOR); 965a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_SET_SENSOR, 966a344afc0SEmily Shaffer nullptr, ipmi_sen_set_sensor, 9670573237fSTom PRIVILEGE_OPERATOR); 96898a23840SMatthew Barth 9690573237fSTom // <Get Sensor Reading> 970a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 971a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING); 972a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING, 973a344afc0SEmily Shaffer nullptr, ipmi_sen_get_sensor_reading, 974a344afc0SEmily Shaffer PRIVILEGE_USER); 975a344afc0SEmily Shaffer 976a344afc0SEmily Shaffer // <Reserve SDR> 977a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 978a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_RESERVE_SDR_REPO); 979a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_RESERVE_SDR_REPO, 980a344afc0SEmily Shaffer nullptr, ipmi_sen_reserve_sdr, 981a344afc0SEmily Shaffer PRIVILEGE_USER); 98298a23840SMatthew Barth 983d06e0e7eSEmily Shaffer // <Get SDR Info> 984a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%x]\n", 985a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SDR_INFO); 986a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SDR_INFO, 987a344afc0SEmily Shaffer nullptr, ipmi_sen_get_sdr_info, 988a344afc0SEmily Shaffer PRIVILEGE_USER); 989bbef71c2SEmily Shaffer 990bbef71c2SEmily Shaffer // <Get SDR> 991bbef71c2SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%x]\n", 992bbef71c2SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SDR); 993bbef71c2SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SDR, 994bbef71c2SEmily Shaffer nullptr, ipmi_sen_get_sdr, 995bbef71c2SEmily Shaffer PRIVILEGE_USER); 996bbef71c2SEmily Shaffer 99798a23840SMatthew Barth return; 99898a23840SMatthew Barth } 999