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 { 424*816e92b5STom Joseph ipmi::sensor::SetSensorReadingReq cmdData = 425*816e92b5STom 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; 48098a23840SMatthew Barth uint8_t type; 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 49298a23840SMatthew Barth if (r < 0) { 49398a23840SMatthew Barth fprintf(stderr, "Failed to find Sensor 0x%02x\n", reqptr->sennum); 49498a23840SMatthew Barth return IPMI_CC_SENSOR_INVALID; 49598a23840SMatthew Barth } 49698a23840SMatthew Barth 497391f3303SEmily Shaffer type = get_type_from_interface(a); 49856003453SBrad Bishop if(type == 0) { 49956003453SBrad Bishop fprintf(stderr, "Failed to find Sensor 0x%02x\n", reqptr->sennum); 50056003453SBrad Bishop return IPMI_CC_SENSOR_INVALID; 50156003453SBrad Bishop } 50298a23840SMatthew Barth 50398a23840SMatthew Barth fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", a.bus, a.path, a.interface); 50498a23840SMatthew Barth 50598a23840SMatthew Barth *data_len=0; 50698a23840SMatthew Barth 50710f4959aSEmily Shaffer int64_t raw_value; 5081fabf229SEmily Shaffer ipmi::sensor::Info sensor; 5091fabf229SEmily Shaffer 51098a23840SMatthew Barth switch(type) { 51198a23840SMatthew Barth case 0xC3: 51298a23840SMatthew Barth case 0xC2: 513558184eaSTom Joseph case 0xC8: 51498a23840SMatthew Barth r = sd_bus_get_property(bus,a.bus, a.path, a.interface, "value", NULL, &reply, "i"); 51598a23840SMatthew Barth if (r < 0) { 51698a23840SMatthew Barth fprintf(stderr, "Failed to call sd_bus_get_property:%d, %s\n", r, strerror(-r)); 51798a23840SMatthew Barth fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", 51898a23840SMatthew Barth a.bus, a.path, a.interface); 51998a23840SMatthew Barth break; 52098a23840SMatthew Barth } 52198a23840SMatthew Barth 52298a23840SMatthew Barth r = sd_bus_message_read(reply, "i", &reading); 52398a23840SMatthew Barth if (r < 0) { 52498a23840SMatthew Barth fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r)); 52598a23840SMatthew Barth break; 52698a23840SMatthew Barth } 52798a23840SMatthew Barth 52898a23840SMatthew Barth printf("Contents of a 0x%02x is 0x%02x\n", type, reading); 52998a23840SMatthew Barth 53098a23840SMatthew Barth rc = IPMI_CC_OK; 53198a23840SMatthew Barth *data_len=sizeof(sensorreadingresp_t); 53298a23840SMatthew Barth 53398a23840SMatthew Barth resp->value = (uint8_t)reading; 53498a23840SMatthew Barth resp->operation = 0; 53598a23840SMatthew Barth resp->indication[0] = 0; 53698a23840SMatthew Barth resp->indication[1] = 0; 53798a23840SMatthew Barth break; 53898a23840SMatthew Barth 5391fabf229SEmily Shaffer case IPMI_SENSOR_TEMP: 5401fabf229SEmily Shaffer case IPMI_SENSOR_VOLTAGE: 5411fabf229SEmily Shaffer case IPMI_SENSOR_CURRENT: 5421fabf229SEmily Shaffer case IPMI_SENSOR_FAN: 5431fabf229SEmily Shaffer // Get reading for /xyz/openbmc_project/Sensor/Value.interface 54410f4959aSEmily Shaffer if(sensors.find(reqptr->sennum) == sensors.end()) 54510f4959aSEmily Shaffer { 54610f4959aSEmily Shaffer fprintf(stderr, "Failed to find config entry for Sensor 0x%02x\n", 54710f4959aSEmily Shaffer reqptr->sennum); 54810f4959aSEmily Shaffer return IPMI_CC_SENSOR_INVALID; 54910f4959aSEmily Shaffer } 55010f4959aSEmily Shaffer 55110f4959aSEmily Shaffer sensor = sensors.at(reqptr->sennum); 552cc941e15SEmily Shaffer if (ipmi::sensor::Mutability::Read != 553cc941e15SEmily Shaffer (sensor.mutability & ipmi::sensor::Mutability::Read)) 554cc941e15SEmily Shaffer { 555cc941e15SEmily Shaffer log<level::ERR>("Sensor was not readable.\n"); 556cc941e15SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 557cc941e15SEmily Shaffer } 558cc941e15SEmily Shaffer 5591fabf229SEmily Shaffer 5601fabf229SEmily Shaffer // Get value 5611fabf229SEmily Shaffer r = sd_bus_get_property_trivial(bus, 5621fabf229SEmily Shaffer a.bus, 5631fabf229SEmily Shaffer a.path, 5641fabf229SEmily Shaffer a.interface, 5651fabf229SEmily Shaffer "Value", 5661fabf229SEmily Shaffer NULL, 5671fabf229SEmily Shaffer 'x', 5681fabf229SEmily Shaffer &raw_value); 5691fabf229SEmily Shaffer if (r < 0) { 5701fabf229SEmily Shaffer fprintf(stderr, 5711fabf229SEmily Shaffer "Failed to call sd_bus_get_property:%d, %s, 'value'\n", 5721fabf229SEmily Shaffer r, 5731fabf229SEmily Shaffer strerror(-r)); 5741fabf229SEmily Shaffer fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", 5751fabf229SEmily Shaffer a.bus, a.path, a.interface); 5761fabf229SEmily Shaffer break; 5771fabf229SEmily Shaffer } 5781fabf229SEmily Shaffer 57910f4959aSEmily Shaffer // Prevent div0 58010f4959aSEmily Shaffer if (sensor.coefficientM == 0) { 58110f4959aSEmily Shaffer sensor.coefficientM = 1; 58210f4959aSEmily Shaffer }; 5831fabf229SEmily Shaffer 58410f4959aSEmily Shaffer resp->value = static_cast<uint8_t>( 58510f4959aSEmily Shaffer (raw_value - sensor.scaledOffset) / sensor.coefficientM); 586bbef71c2SEmily Shaffer resp->operation = 1<<6; // scanning enabled 587bbef71c2SEmily Shaffer resp->indication[0] = 0; // not a threshold sensor. ignore 5881fabf229SEmily Shaffer resp->indication[1] = 0; 5891fabf229SEmily Shaffer rc = IPMI_CC_OK; 5901fabf229SEmily Shaffer *data_len=sizeof(sensorreadingresp_t); 5911fabf229SEmily Shaffer break; 59260cac721STom Joseph case IPMI_SENSOR_TPM: 59360cac721STom Joseph { 59460cac721STom Joseph auto iter = sensors.find(reqptr->sennum); 59560cac721STom Joseph if (iter == sensors.end()) 59660cac721STom Joseph { 59760cac721STom Joseph return IPMI_CC_SENSOR_INVALID; 59860cac721STom Joseph } 5991fabf229SEmily Shaffer 60060cac721STom Joseph auto& interfaceList = iter->second.propertyInterfaces; 60160cac721STom Joseph if (interfaceList.empty()) 60260cac721STom Joseph { 60360cac721STom Joseph log<level::ERR>("Interface List empty for the sensor", 60460cac721STom Joseph entry("SENSOR_NUMBER=%d", reqptr->sennum)); 60560cac721STom Joseph return IPMI_CC_UNSPECIFIED_ERROR; 60660cac721STom Joseph } 60760cac721STom Joseph 60860cac721STom Joseph /* For the TPM sensor there is no reading value and sensor scanning 60960cac721STom Joseph * is disabled. This is a discrete sensor and only the 61060cac721STom Joseph * corresponding state is asserted. 61160cac721STom Joseph */ 61260cac721STom Joseph resp->value = 0; 61360cac721STom Joseph resp->operation = 0; 61460cac721STom Joseph resp->indication[0] = 0; 61560cac721STom Joseph resp->indication[1] = 0; 61660cac721STom Joseph 61760cac721STom Joseph try 61860cac721STom Joseph { 61960cac721STom Joseph for (const auto& interface : interfaceList) 62060cac721STom Joseph { 62160cac721STom Joseph for (const auto& property : interface.second) 62260cac721STom Joseph { 62360cac721STom Joseph sdbusplus::bus::bus dbus{ipmid_get_sd_bus_connection()}; 62460cac721STom Joseph 62560cac721STom Joseph auto service = ipmi::getService( 62660cac721STom Joseph dbus, 62760cac721STom Joseph interface.first, 62860cac721STom Joseph iter->second.sensorPath); 62960cac721STom Joseph 63060cac721STom Joseph auto propValue = ipmi::getDbusProperty( 63160cac721STom Joseph dbus, service, iter->second.sensorPath, 63260cac721STom Joseph interface.first, property.first); 63360cac721STom Joseph 63460cac721STom Joseph auto tpmStatus = propValue.get<bool>(); 63560cac721STom Joseph 63660cac721STom Joseph for (const auto& value : property.second) 63760cac721STom Joseph { 63860cac721STom Joseph if (tpmStatus == (value.second.assert).get<bool>()) 63960cac721STom Joseph { 64060cac721STom Joseph /* 64160cac721STom Joseph * The discrete sensors support upto 14 states. 64260cac721STom Joseph * The assertion states for discrete sensors are 64360cac721STom Joseph * stored in 2 bytes, 0-7 in Byte 4 of the 64460cac721STom Joseph * response and 8-14 in Byte 5 of the response. 64560cac721STom Joseph */ 64660cac721STom Joseph resp->indication[0] |= 1 << (value.first); 64760cac721STom Joseph break; 64860cac721STom Joseph } 64960cac721STom Joseph } 65060cac721STom Joseph } 65160cac721STom Joseph } 65260cac721STom Joseph 65360cac721STom Joseph rc = IPMI_CC_OK; 65460cac721STom Joseph *data_len = sizeof(sensorreadingresp_t); 65560cac721STom Joseph } 65660cac721STom Joseph catch (InternalFailure& e) 65760cac721STom Joseph { 65860cac721STom Joseph return IPMI_CC_UNSPECIFIED_ERROR; 65960cac721STom Joseph } 66060cac721STom Joseph break; 66160cac721STom Joseph } 66298a23840SMatthew Barth default: 66398a23840SMatthew Barth *data_len=0; 66498a23840SMatthew Barth rc = IPMI_CC_SENSOR_INVALID; 66598a23840SMatthew Barth break; 66698a23840SMatthew Barth } 66798a23840SMatthew Barth 66898a23840SMatthew Barth reply = sd_bus_message_unref(reply); 66998a23840SMatthew Barth 67098a23840SMatthew Barth return rc; 67198a23840SMatthew Barth } 67298a23840SMatthew Barth 67398a23840SMatthew Barth ipmi_ret_t ipmi_sen_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 67498a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 67598a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 67698a23840SMatthew Barth { 67770aa8d96SNan Li ipmi_ret_t rc = IPMI_CC_INVALID; 67898a23840SMatthew Barth 67998a23840SMatthew Barth printf("IPMI S/E Wildcard Netfn:[0x%X], Cmd:[0x%X]\n",netfn,cmd); 68098a23840SMatthew Barth *data_len = 0; 68198a23840SMatthew Barth 68298a23840SMatthew Barth return rc; 68398a23840SMatthew Barth } 68498a23840SMatthew Barth 685d06e0e7eSEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 686d06e0e7eSEmily Shaffer ipmi_request_t request, 687d06e0e7eSEmily Shaffer ipmi_response_t response, 688d06e0e7eSEmily Shaffer ipmi_data_len_t data_len, 689d06e0e7eSEmily Shaffer ipmi_context_t context) 690d06e0e7eSEmily Shaffer { 691d06e0e7eSEmily Shaffer auto resp = static_cast<get_sdr_info::GetSdrInfoResp*>(response); 692d06e0e7eSEmily Shaffer if (request == nullptr || 693d06e0e7eSEmily Shaffer get_sdr_info::request::get_count(request) == false) 694d06e0e7eSEmily Shaffer { 695d06e0e7eSEmily Shaffer // Get Sensor Count 696d06e0e7eSEmily Shaffer resp->count = sensors.size(); 697d06e0e7eSEmily Shaffer } 698d06e0e7eSEmily Shaffer else 699d06e0e7eSEmily Shaffer { 700d06e0e7eSEmily Shaffer resp->count = 1; 701d06e0e7eSEmily Shaffer } 702d06e0e7eSEmily Shaffer 703d06e0e7eSEmily Shaffer // Multiple LUNs not supported. 704d06e0e7eSEmily Shaffer namespace response = get_sdr_info::response; 705d06e0e7eSEmily Shaffer response::set_lun_present(0, &(resp->luns_and_dynamic_population)); 706d06e0e7eSEmily Shaffer response::set_lun_not_present(1, &(resp->luns_and_dynamic_population)); 707d06e0e7eSEmily Shaffer response::set_lun_not_present(2, &(resp->luns_and_dynamic_population)); 708d06e0e7eSEmily Shaffer response::set_lun_not_present(3, &(resp->luns_and_dynamic_population)); 709d06e0e7eSEmily Shaffer response::set_static_population(&(resp->luns_and_dynamic_population)); 710d06e0e7eSEmily Shaffer 711d06e0e7eSEmily Shaffer *data_len = SDR_INFO_RESP_SIZE; 712d06e0e7eSEmily Shaffer 713d06e0e7eSEmily Shaffer return IPMI_CC_OK; 714d06e0e7eSEmily Shaffer } 715d06e0e7eSEmily Shaffer 716a344afc0SEmily Shaffer ipmi_ret_t ipmi_sen_reserve_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 717a344afc0SEmily Shaffer ipmi_request_t request, 718a344afc0SEmily Shaffer ipmi_response_t response, 719a344afc0SEmily Shaffer ipmi_data_len_t data_len, 720a344afc0SEmily Shaffer ipmi_context_t context) 721a344afc0SEmily Shaffer { 722a344afc0SEmily Shaffer // A constant reservation ID is okay until we implement add/remove SDR. 723a344afc0SEmily Shaffer const uint16_t reservation_id = 1; 724a344afc0SEmily Shaffer *(uint16_t*)response = reservation_id; 7255a5a6282SEmily Shaffer *data_len = sizeof(uint16_t); 726a344afc0SEmily Shaffer 727a344afc0SEmily Shaffer printf("Created new IPMI SDR reservation ID %d\n", *(uint16_t*)response); 728a344afc0SEmily Shaffer return IPMI_CC_OK; 729a344afc0SEmily Shaffer } 73098a23840SMatthew Barth 731cc941e15SEmily Shaffer void setUnitFieldsForObject(sd_bus *bus, 732cc941e15SEmily Shaffer const dbus_interface_t &iface, 733bbef71c2SEmily Shaffer const ipmi::sensor::Info *info, 734cc941e15SEmily Shaffer get_sdr::SensorDataFullRecordBody *body) 735bbef71c2SEmily Shaffer { 7361bb0d387SDeepak Kodihalli if (info->propertyInterfaces.begin()->first == 737bbef71c2SEmily Shaffer "xyz.openbmc_project.Sensor.Value") 738bbef71c2SEmily Shaffer { 739cc941e15SEmily Shaffer std::string result {}; 740cc941e15SEmily Shaffer char *raw_cstr = NULL; 741bbef71c2SEmily Shaffer if (0 > sd_bus_get_property_string(bus, iface.bus, iface.path, 742bbef71c2SEmily Shaffer iface.interface, "Unit", NULL, 743cc941e15SEmily Shaffer &raw_cstr)) 744cc941e15SEmily Shaffer { 745cc941e15SEmily Shaffer log<level::WARNING>("Unit interface missing.", 746cc941e15SEmily Shaffer entry("bus=%s, path=%s", iface.bus, iface.path)); 747bbef71c2SEmily Shaffer } 748cc941e15SEmily Shaffer else 749cc941e15SEmily Shaffer { 750cc941e15SEmily Shaffer result = raw_cstr; 751cc941e15SEmily Shaffer } 752cc941e15SEmily Shaffer free(raw_cstr); 753bbef71c2SEmily Shaffer 754bbef71c2SEmily Shaffer namespace server = sdbusplus::xyz::openbmc_project::Sensor::server; 755cc941e15SEmily Shaffer try { 756cc941e15SEmily Shaffer auto unit = server::Value::convertUnitFromString(result); 757bbef71c2SEmily Shaffer // Unit strings defined in 758bbef71c2SEmily Shaffer // phosphor-dbus-interfaces/xyz/openbmc_project/Sensor/Value.interface.yaml 759bbef71c2SEmily Shaffer switch (unit) 760bbef71c2SEmily Shaffer { 761bbef71c2SEmily Shaffer case server::Value::Unit::DegreesC: 762bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_DEGREES_C; 763bbef71c2SEmily Shaffer break; 764bbef71c2SEmily Shaffer case server::Value::Unit::RPMS: 765bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_REVOLUTIONS; // revolutions 766bbef71c2SEmily Shaffer get_sdr::body::set_rate_unit(0b100, body); // per minute 767bbef71c2SEmily Shaffer break; 768bbef71c2SEmily Shaffer case server::Value::Unit::Volts: 769bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_VOLTS; 770bbef71c2SEmily Shaffer break; 771bbef71c2SEmily Shaffer case server::Value::Unit::Meters: 772bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_METERS; 773bbef71c2SEmily Shaffer break; 774bbef71c2SEmily Shaffer case server::Value::Unit::Amperes: 775bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_AMPERES; 776bbef71c2SEmily Shaffer break; 777bbef71c2SEmily Shaffer case server::Value::Unit::Joules: 778bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_JOULES; 779bbef71c2SEmily Shaffer break; 780bbef71c2SEmily Shaffer default: 781cc941e15SEmily Shaffer // Cannot be hit. 782cc941e15SEmily Shaffer fprintf(stderr, "Unknown value unit type: = %s\n", result.c_str()); 783cc941e15SEmily Shaffer } 784cc941e15SEmily Shaffer } 785cc941e15SEmily Shaffer catch (sdbusplus::exception::InvalidEnumString e) 786cc941e15SEmily Shaffer { 787cc941e15SEmily Shaffer log<level::WARNING>("Warning: no unit provided for sensor!"); 788cc941e15SEmily Shaffer } 789cc941e15SEmily Shaffer } 790bbef71c2SEmily Shaffer } 791bbef71c2SEmily Shaffer 792cc941e15SEmily Shaffer int64_t getScaleForObject(sd_bus *bus, 793cc941e15SEmily Shaffer const dbus_interface_t& iface, 794cc941e15SEmily Shaffer const ipmi::sensor::Info *info) 795cc941e15SEmily Shaffer { 796cc941e15SEmily Shaffer int64_t result = 0; 797cc941e15SEmily Shaffer if (info->propertyInterfaces.begin()->first == 798cc941e15SEmily Shaffer "xyz.openbmc_project.Sensor.Value") 799cc941e15SEmily Shaffer { 80010f4959aSEmily Shaffer if (0 > sd_bus_get_property_trivial(bus, 80110f4959aSEmily Shaffer iface.bus, 80210f4959aSEmily Shaffer iface.path, 80310f4959aSEmily Shaffer iface.interface, 80410f4959aSEmily Shaffer "Scale", 80510f4959aSEmily Shaffer NULL, 80610f4959aSEmily Shaffer 'x', 807cc941e15SEmily Shaffer &result)) { 808cc941e15SEmily Shaffer log<level::WARNING>("Scale interface missing.", 809cc941e15SEmily Shaffer entry("bus=%s, path=%s", iface.bus, iface.path)); 81010f4959aSEmily Shaffer } 811cc941e15SEmily Shaffer } 812cc941e15SEmily Shaffer 813cc941e15SEmily Shaffer return result; 814cc941e15SEmily Shaffer } 815cc941e15SEmily Shaffer 816cc941e15SEmily Shaffer ipmi_ret_t populate_record_from_dbus(get_sdr::SensorDataFullRecordBody *body, 817cc941e15SEmily Shaffer const ipmi::sensor::Info *info, 818cc941e15SEmily Shaffer ipmi_data_len_t data_len) 819cc941e15SEmily Shaffer { 820cc941e15SEmily Shaffer /* Functional sensor case */ 821cc941e15SEmily Shaffer if (isAnalogSensor(info->propertyInterfaces.begin()->first)) 822cc941e15SEmily Shaffer { 823cc941e15SEmily Shaffer // Get bus 824cc941e15SEmily Shaffer sd_bus *bus = ipmid_get_sd_bus_connection(); 825cc941e15SEmily Shaffer dbus_interface_t iface; 826cc941e15SEmily Shaffer 827cc941e15SEmily Shaffer if (0 > find_openbmc_path(body->entity_id, &iface)) 828cc941e15SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 829cc941e15SEmily Shaffer 830cc941e15SEmily Shaffer body->sensor_units_1 = 0; // unsigned, no rate, no modifier, not a % 831cc941e15SEmily Shaffer 832cc941e15SEmily Shaffer /* Unit info */ 833cc941e15SEmily Shaffer setUnitFieldsForObject(bus, iface, info, body); 834cc941e15SEmily Shaffer 835cc941e15SEmily Shaffer /* Modifiers to reading info */ 836cc941e15SEmily Shaffer // Get scale 837cc941e15SEmily Shaffer int64_t scale = getScaleForObject(bus, iface, info); 83810f4959aSEmily Shaffer 83910f4959aSEmily Shaffer get_sdr::body::set_b(info->coefficientB, body); 84010f4959aSEmily Shaffer get_sdr::body::set_m(info->coefficientM, body); 84110f4959aSEmily Shaffer get_sdr::body::set_b_exp(info->exponentB, body); 84210f4959aSEmily Shaffer get_sdr::body::set_r_exp(scale, body); 843bbef71c2SEmily Shaffer 844bbef71c2SEmily Shaffer /* ID string */ 845bbef71c2SEmily Shaffer std::string id_string = info->sensorPath.substr( 846bbef71c2SEmily Shaffer info->sensorPath.find_last_of('/')+1, info->sensorPath.length()); 847bbef71c2SEmily Shaffer get_sdr::body::set_id_type(0b00, body); // 00 = unicode 848bbef71c2SEmily Shaffer if (id_string.length() > FULL_RECORD_ID_STR_MAX_LENGTH) 849bbef71c2SEmily Shaffer { 850bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(FULL_RECORD_ID_STR_MAX_LENGTH, body); 851bbef71c2SEmily Shaffer } 852bbef71c2SEmily Shaffer else 853bbef71c2SEmily Shaffer { 854bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(id_string.length(), body); 855bbef71c2SEmily Shaffer } 856bbef71c2SEmily Shaffer strncpy(body->id_string, id_string.c_str(), 857bbef71c2SEmily Shaffer get_sdr::body::get_id_strlen(body)); 858bbef71c2SEmily Shaffer } 859bbef71c2SEmily Shaffer 860bbef71c2SEmily Shaffer return IPMI_CC_OK; 861bbef71c2SEmily Shaffer }; 862bbef71c2SEmily Shaffer 863bbef71c2SEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 864bbef71c2SEmily Shaffer ipmi_request_t request, ipmi_response_t response, 865bbef71c2SEmily Shaffer ipmi_data_len_t data_len, ipmi_context_t context) 866bbef71c2SEmily Shaffer { 867bbef71c2SEmily Shaffer ipmi_ret_t ret = IPMI_CC_OK; 868bbef71c2SEmily Shaffer get_sdr::GetSdrReq *req = (get_sdr::GetSdrReq*)request; 869bbef71c2SEmily Shaffer get_sdr::GetSdrResp *resp = (get_sdr::GetSdrResp*)response; 870bbef71c2SEmily Shaffer get_sdr::SensorDataFullRecord record = {0}; 871bbef71c2SEmily Shaffer if (req != NULL) 872bbef71c2SEmily Shaffer { 873bbef71c2SEmily Shaffer // Note: we use an iterator so we can provide the next ID at the end of 874bbef71c2SEmily Shaffer // the call. 875bbef71c2SEmily Shaffer auto sensor = sensors.begin(); 876bbef71c2SEmily Shaffer 877bbef71c2SEmily Shaffer // At the beginning of a scan, the host side will send us id=0. 878bbef71c2SEmily Shaffer if (get_sdr::request::get_record_id(req) != 0) 879bbef71c2SEmily Shaffer { 880bbef71c2SEmily Shaffer sensor = sensors.find(get_sdr::request::get_record_id(req)); 881bbef71c2SEmily Shaffer if(sensor == sensors.end()) { 882bbef71c2SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 883bbef71c2SEmily Shaffer } 884bbef71c2SEmily Shaffer } 885bbef71c2SEmily Shaffer 886bbef71c2SEmily Shaffer uint8_t sensor_id = sensor->first; 887bbef71c2SEmily Shaffer 888bbef71c2SEmily Shaffer /* Header */ 889bbef71c2SEmily Shaffer get_sdr::header::set_record_id(sensor_id, &(record.header)); 890bbef71c2SEmily Shaffer record.header.sdr_version = 0x51; // Based on IPMI Spec v2.0 rev 1.1 891bbef71c2SEmily Shaffer record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD; 892bbef71c2SEmily Shaffer record.header.record_length = sizeof(get_sdr::SensorDataFullRecord); 893bbef71c2SEmily Shaffer 894bbef71c2SEmily Shaffer /* Key */ 895bbef71c2SEmily Shaffer record.key.sensor_number = sensor_id; 896bbef71c2SEmily Shaffer 897bbef71c2SEmily Shaffer /* Body */ 898bbef71c2SEmily Shaffer record.body.entity_id = sensor_id; 899bbef71c2SEmily Shaffer record.body.sensor_type = sensor->second.sensorType; 900bbef71c2SEmily Shaffer record.body.event_reading_type = sensor->second.sensorReadingType; 901bbef71c2SEmily Shaffer 902bbef71c2SEmily Shaffer // Set the type-specific details given the DBus interface 903bbef71c2SEmily Shaffer ret = populate_record_from_dbus(&(record.body), &(sensor->second), 904bbef71c2SEmily Shaffer data_len); 905bbef71c2SEmily Shaffer 906bbef71c2SEmily Shaffer if (++sensor == sensors.end()) 907bbef71c2SEmily Shaffer { 908bbef71c2SEmily Shaffer get_sdr::response::set_next_record_id(0xFFFF, resp); // last record 909bbef71c2SEmily Shaffer } 910bbef71c2SEmily Shaffer else 911bbef71c2SEmily Shaffer { 912bbef71c2SEmily Shaffer get_sdr::response::set_next_record_id(sensor->first, resp); 913bbef71c2SEmily Shaffer } 914bbef71c2SEmily Shaffer 915bbef71c2SEmily Shaffer *data_len = sizeof(get_sdr::GetSdrResp) - req->offset; 916bbef71c2SEmily Shaffer memcpy(resp->record_data, (char*)&record + req->offset, 917bbef71c2SEmily Shaffer sizeof(get_sdr::SensorDataFullRecord) - req->offset); 918bbef71c2SEmily Shaffer } 919bbef71c2SEmily Shaffer 920bbef71c2SEmily Shaffer return ret; 921bbef71c2SEmily Shaffer } 922bbef71c2SEmily Shaffer 923bbef71c2SEmily Shaffer 92498a23840SMatthew Barth void register_netfn_sen_functions() 92598a23840SMatthew Barth { 9260573237fSTom // <Wildcard Command> 927a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 928a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_WILDCARD); 929a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_WILDCARD, 930a344afc0SEmily Shaffer nullptr, ipmi_sen_wildcard, 9310573237fSTom PRIVILEGE_USER); 93298a23840SMatthew Barth 9330573237fSTom // <Get Sensor Type> 934a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 935a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE); 936a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE, 937a344afc0SEmily Shaffer nullptr, ipmi_sen_get_sensor_type, 9380573237fSTom PRIVILEGE_USER); 93998a23840SMatthew Barth 9400573237fSTom // <Set Sensor Reading and Event Status> 941a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 942a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_SET_SENSOR); 943a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_SET_SENSOR, 944a344afc0SEmily Shaffer nullptr, ipmi_sen_set_sensor, 9450573237fSTom PRIVILEGE_OPERATOR); 94698a23840SMatthew Barth 9470573237fSTom // <Get Sensor Reading> 948a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 949a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING); 950a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING, 951a344afc0SEmily Shaffer nullptr, ipmi_sen_get_sensor_reading, 952a344afc0SEmily Shaffer PRIVILEGE_USER); 953a344afc0SEmily Shaffer 954a344afc0SEmily Shaffer // <Reserve SDR> 955a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", 956a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_RESERVE_SDR_REPO); 957a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_RESERVE_SDR_REPO, 958a344afc0SEmily Shaffer nullptr, ipmi_sen_reserve_sdr, 959a344afc0SEmily Shaffer PRIVILEGE_USER); 96098a23840SMatthew Barth 961d06e0e7eSEmily Shaffer // <Get SDR Info> 962a344afc0SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%x]\n", 963a344afc0SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SDR_INFO); 964a344afc0SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SDR_INFO, 965a344afc0SEmily Shaffer nullptr, ipmi_sen_get_sdr_info, 966a344afc0SEmily Shaffer PRIVILEGE_USER); 967bbef71c2SEmily Shaffer 968bbef71c2SEmily Shaffer // <Get SDR> 969bbef71c2SEmily Shaffer printf("Registering NetFn:[0x%X], Cmd:[0x%x]\n", 970bbef71c2SEmily Shaffer NETFUN_SENSOR, IPMI_CMD_GET_SDR); 971bbef71c2SEmily Shaffer ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SDR, 972bbef71c2SEmily Shaffer nullptr, ipmi_sen_get_sdr, 973bbef71c2SEmily Shaffer PRIVILEGE_USER); 974bbef71c2SEmily Shaffer 97598a23840SMatthew Barth return; 97698a23840SMatthew Barth } 977