146470a38SPatrick Venture #include "sensorhandler.hpp" 20b02be92SPatrick Venture 30b02be92SPatrick Venture #include "fruread.hpp" 40b02be92SPatrick Venture #include "ipmid.hpp" 50b02be92SPatrick Venture #include "types.hpp" 60b02be92SPatrick Venture #include "utils.hpp" 70b02be92SPatrick Venture 846470a38SPatrick Venture #include <host-ipmid/ipmid-api.h> 9d700e76aSTom #include <mapper.h> 1098a23840SMatthew Barth #include <systemd/sd-bus.h> 110b02be92SPatrick Venture 120b02be92SPatrick Venture #include <bitset> 13586d35b4SPatrick Venture #include <cmath> 14b51bf9c8SPatrick Venture #include <cstring> 1518e99992SDhruvaraj Subhashchandran #include <phosphor-logging/elog-errors.hpp> 160b02be92SPatrick Venture #include <phosphor-logging/log.hpp> 170b02be92SPatrick Venture #include <set> 180b02be92SPatrick Venture #include <xyz/openbmc_project/Common/error.hpp> 190b02be92SPatrick Venture #include <xyz/openbmc_project/Sensor/Value/server.hpp> 200b02be92SPatrick Venture 21e0cc8553SRatan Gupta static constexpr uint8_t fruInventoryDevice = 0x10; 22e0cc8553SRatan Gupta static constexpr uint8_t IPMIFruInventory = 0x02; 23e0cc8553SRatan Gupta static constexpr uint8_t BMCSlaveAddress = 0x20; 24e0cc8553SRatan Gupta 2598a23840SMatthew Barth extern int updateSensorRecordFromSSRAESC(const void*); 26d700e76aSTom extern sd_bus* bus; 27be703f71STom Joseph extern const ipmi::sensor::IdInfoMap sensors; 28e0cc8553SRatan Gupta extern const FruMap frus; 29e0cc8553SRatan Gupta 30be703f71STom Joseph using namespace phosphor::logging; 3118e99992SDhruvaraj Subhashchandran using InternalFailure = 3218e99992SDhruvaraj Subhashchandran sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 3398a23840SMatthew Barth 34*37544429SJames Feist namespace variant_ns = sdbusplus::message::variant_ns; 35*37544429SJames Feist 3698a23840SMatthew Barth void register_netfn_sen_functions() __attribute__((constructor)); 3798a23840SMatthew Barth 380b02be92SPatrick Venture struct sensorTypemap_t 390b02be92SPatrick Venture { 4098a23840SMatthew Barth uint8_t number; 4198a23840SMatthew Barth uint8_t typecode; 4298a23840SMatthew Barth char dbusname[32]; 4398a23840SMatthew Barth }; 4498a23840SMatthew Barth 4598a23840SMatthew Barth sensorTypemap_t g_SensorTypeMap[] = { 4698a23840SMatthew Barth 4798a23840SMatthew Barth {0x01, 0x6F, "Temp"}, 4898a23840SMatthew Barth {0x0C, 0x6F, "DIMM"}, 4998a23840SMatthew Barth {0x0C, 0x6F, "MEMORY_BUFFER"}, 5098a23840SMatthew Barth {0x07, 0x6F, "PROC"}, 5198a23840SMatthew Barth {0x07, 0x6F, "CORE"}, 5298a23840SMatthew Barth {0x07, 0x6F, "CPU"}, 5398a23840SMatthew Barth {0x0F, 0x6F, "BootProgress"}, 540b02be92SPatrick Venture {0xe9, 0x09, "OccStatus"}, // E9 is an internal mapping to handle sensor 550b02be92SPatrick Venture // type code os 0x09 5698a23840SMatthew Barth {0xC3, 0x6F, "BootCount"}, 5798a23840SMatthew Barth {0x1F, 0x6F, "OperatingSystemStatus"}, 5898a23840SMatthew Barth {0x12, 0x6F, "SYSTEM_EVENT"}, 5998a23840SMatthew Barth {0xC7, 0x03, "SYSTEM"}, 6098a23840SMatthew Barth {0xC7, 0x03, "MAIN_PLANAR"}, 6198a23840SMatthew Barth {0xC2, 0x6F, "PowerCap"}, 62558184eaSTom Joseph {0x0b, 0xCA, "PowerSupplyRedundancy"}, 630661beb1SJayanth Othayoth {0xDA, 0x03, "TurboAllowed"}, 64558184eaSTom Joseph {0xD8, 0xC8, "PowerSupplyDerating"}, 6598a23840SMatthew Barth {0xFF, 0x00, ""}, 6698a23840SMatthew Barth }; 6798a23840SMatthew Barth 680b02be92SPatrick Venture struct sensor_data_t 690b02be92SPatrick Venture { 7098a23840SMatthew Barth uint8_t sennum; 7198a23840SMatthew Barth } __attribute__((packed)); 7298a23840SMatthew Barth 730b02be92SPatrick Venture struct sensorreadingresp_t 740b02be92SPatrick Venture { 7598a23840SMatthew Barth uint8_t value; 7698a23840SMatthew Barth uint8_t operation; 7798a23840SMatthew Barth uint8_t indication[2]; 7898a23840SMatthew Barth } __attribute__((packed)); 7998a23840SMatthew Barth 800b02be92SPatrick Venture int get_bus_for_path(const char* path, char** busname) 810b02be92SPatrick Venture { 822ae09b9aSEmily Shaffer return mapper_get_service(bus, path, busname); 832ae09b9aSEmily Shaffer } 84d700e76aSTom 852ae09b9aSEmily Shaffer // Use a lookup table to find the interface name of a specific sensor 862ae09b9aSEmily Shaffer // This will be used until an alternative is found. this is the first 872ae09b9aSEmily Shaffer // step for mapping IPMI 880b02be92SPatrick Venture int find_openbmc_path(uint8_t num, dbus_interface_t* interface) 890b02be92SPatrick Venture { 902ae09b9aSEmily Shaffer int rc; 912ae09b9aSEmily Shaffer 922ae09b9aSEmily Shaffer const auto& sensor_it = sensors.find(num); 932ae09b9aSEmily Shaffer if (sensor_it == sensors.end()) 942ae09b9aSEmily Shaffer { 95ba23ff71SAdriana Kobylak // The sensor map does not contain the sensor requested 96ba23ff71SAdriana Kobylak return -EINVAL; 972ae09b9aSEmily Shaffer } 982ae09b9aSEmily Shaffer 992ae09b9aSEmily Shaffer const auto& info = sensor_it->second; 1002ae09b9aSEmily Shaffer 1018451edf5SPatrick Williams char* busname = nullptr; 1022ae09b9aSEmily Shaffer rc = get_bus_for_path(info.sensorPath.c_str(), &busname); 1030b02be92SPatrick Venture if (rc < 0) 1040b02be92SPatrick Venture { 105b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to get %s busname: %s\n", 1060b02be92SPatrick Venture info.sensorPath.c_str(), busname); 1072ae09b9aSEmily Shaffer goto final; 1082ae09b9aSEmily Shaffer } 1092ae09b9aSEmily Shaffer 1102ae09b9aSEmily Shaffer interface->sensortype = info.sensorType; 1112ae09b9aSEmily Shaffer strcpy(interface->bus, busname); 1122ae09b9aSEmily Shaffer strcpy(interface->path, info.sensorPath.c_str()); 1132ae09b9aSEmily Shaffer // Take the interface name from the beginning of the DbusInterfaceMap. This 1142ae09b9aSEmily Shaffer // works for the Value interface but may not suffice for more complex 1152ae09b9aSEmily Shaffer // sensors. 1162ae09b9aSEmily Shaffer // tracked https://github.com/openbmc/phosphor-host-ipmid/issues/103 1170b02be92SPatrick Venture strcpy(interface->interface, 1180b02be92SPatrick Venture info.propertyInterfaces.begin()->first.c_str()); 1192ae09b9aSEmily Shaffer interface->sensornumber = num; 1202ae09b9aSEmily Shaffer 1212ae09b9aSEmily Shaffer final: 1222ae09b9aSEmily Shaffer free(busname); 1232ae09b9aSEmily Shaffer return rc; 1242ae09b9aSEmily Shaffer } 1252ae09b9aSEmily Shaffer 126d700e76aSTom ///////////////////////////////////////////////////////////////////// 127d700e76aSTom // 128d700e76aSTom // Routines used by ipmi commands wanting to interact on the dbus 129d700e76aSTom // 130d700e76aSTom ///////////////////////////////////////////////////////////////////// 1310b02be92SPatrick Venture int set_sensor_dbus_state_s(uint8_t number, const char* method, 1320b02be92SPatrick Venture const char* value) 1330b02be92SPatrick Venture { 134d700e76aSTom 135d700e76aSTom dbus_interface_t a; 136d700e76aSTom int r; 137d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 138d700e76aSTom sd_bus_message* m = NULL; 139d700e76aSTom 140b51bf9c8SPatrick Venture std::fprintf(ipmidbus, 1410b02be92SPatrick Venture "Attempting to set a dbus Variant Sensor 0x%02x via %s with a " 1420b02be92SPatrick Venture "value of %s\n", 143d700e76aSTom number, method, value); 144d700e76aSTom 1452ae09b9aSEmily Shaffer r = find_openbmc_path(number, &a); 146d700e76aSTom 1470b02be92SPatrick Venture if (r < 0) 1480b02be92SPatrick Venture { 149b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); 150d700e76aSTom return 0; 151d700e76aSTom } 152d700e76aSTom 1530b02be92SPatrick Venture r = sd_bus_message_new_method_call(bus, &m, a.bus, a.path, a.interface, 1540b02be92SPatrick Venture method); 1550b02be92SPatrick Venture if (r < 0) 1560b02be92SPatrick Venture { 157b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a method call: %s", 158b51bf9c8SPatrick Venture strerror(-r)); 159d700e76aSTom goto final; 160d700e76aSTom } 161d700e76aSTom 162d700e76aSTom r = sd_bus_message_append(m, "v", "s", value); 1630b02be92SPatrick Venture if (r < 0) 1640b02be92SPatrick Venture { 165b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a input parameter: %s", 166b51bf9c8SPatrick Venture strerror(-r)); 167d700e76aSTom goto final; 168d700e76aSTom } 169d700e76aSTom 170d700e76aSTom r = sd_bus_call(bus, m, 0, &error, NULL); 1710b02be92SPatrick Venture if (r < 0) 1720b02be92SPatrick Venture { 173b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to call the method: %s", strerror(-r)); 174d700e76aSTom } 175d700e76aSTom 176d700e76aSTom final: 177d700e76aSTom sd_bus_error_free(&error); 178d700e76aSTom m = sd_bus_message_unref(m); 179d700e76aSTom 180d700e76aSTom return 0; 181d700e76aSTom } 1820b02be92SPatrick Venture int set_sensor_dbus_state_y(uint8_t number, const char* method, 1830b02be92SPatrick Venture const uint8_t value) 1840b02be92SPatrick Venture { 185d700e76aSTom 186d700e76aSTom dbus_interface_t a; 187d700e76aSTom int r; 188d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 189d700e76aSTom sd_bus_message* m = NULL; 190d700e76aSTom 191b51bf9c8SPatrick Venture std::fprintf(ipmidbus, 1920b02be92SPatrick Venture "Attempting to set a dbus Variant Sensor 0x%02x via %s with a " 1930b02be92SPatrick Venture "value of 0x%02x\n", 194d700e76aSTom number, method, value); 195d700e76aSTom 1962ae09b9aSEmily Shaffer r = find_openbmc_path(number, &a); 197d700e76aSTom 1980b02be92SPatrick Venture if (r < 0) 1990b02be92SPatrick Venture { 200b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); 201d700e76aSTom return 0; 202d700e76aSTom } 203d700e76aSTom 2040b02be92SPatrick Venture r = sd_bus_message_new_method_call(bus, &m, a.bus, a.path, a.interface, 2050b02be92SPatrick Venture method); 2060b02be92SPatrick Venture if (r < 0) 2070b02be92SPatrick Venture { 208b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a method call: %s", 209b51bf9c8SPatrick Venture strerror(-r)); 210d700e76aSTom goto final; 211d700e76aSTom } 212d700e76aSTom 213d700e76aSTom r = sd_bus_message_append(m, "v", "i", value); 2140b02be92SPatrick Venture if (r < 0) 2150b02be92SPatrick Venture { 216b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a input parameter: %s", 217b51bf9c8SPatrick Venture strerror(-r)); 218d700e76aSTom goto final; 219d700e76aSTom } 220d700e76aSTom 221d700e76aSTom r = sd_bus_call(bus, m, 0, &error, NULL); 2220b02be92SPatrick Venture if (r < 0) 2230b02be92SPatrick Venture { 224b51bf9c8SPatrick Venture std::fprintf(stderr, "12 Failed to call the method: %s", strerror(-r)); 225d700e76aSTom } 226d700e76aSTom 227d700e76aSTom final: 228d700e76aSTom sd_bus_error_free(&error); 229d700e76aSTom m = sd_bus_message_unref(m); 230d700e76aSTom 231d700e76aSTom return 0; 232d700e76aSTom } 233d700e76aSTom 2340b02be92SPatrick Venture uint8_t dbus_to_sensor_type(char* p) 2350b02be92SPatrick Venture { 23698a23840SMatthew Barth 23798a23840SMatthew Barth sensorTypemap_t* s = g_SensorTypeMap; 23898a23840SMatthew Barth char r = 0; 2390b02be92SPatrick Venture while (s->number != 0xFF) 2400b02be92SPatrick Venture { 2410b02be92SPatrick Venture if (!strcmp(s->dbusname, p)) 2420b02be92SPatrick Venture { 243558184eaSTom Joseph r = s->typecode; 24498a23840SMatthew Barth break; 24598a23840SMatthew Barth } 24698a23840SMatthew Barth s++; 24798a23840SMatthew Barth } 24898a23840SMatthew Barth 24998a23840SMatthew Barth if (s->number == 0xFF) 25098a23840SMatthew Barth printf("Failed to find Sensor Type %s\n", p); 25198a23840SMatthew Barth 25298a23840SMatthew Barth return r; 25398a23840SMatthew Barth } 25498a23840SMatthew Barth 2550b02be92SPatrick Venture uint8_t get_type_from_interface(dbus_interface_t dbus_if) 2560b02be92SPatrick Venture { 25798a23840SMatthew Barth 25898a23840SMatthew Barth char* p; 25956003453SBrad Bishop uint8_t type; 26098a23840SMatthew Barth 26198a23840SMatthew Barth // This is where sensors that do not exist in dbus but do 26298a23840SMatthew Barth // exist in the host code stop. This should indicate it 26398a23840SMatthew Barth // is not a supported sensor 2640b02be92SPatrick Venture if (dbus_if.interface[0] == 0) 2650b02be92SPatrick Venture { 2660b02be92SPatrick Venture return 0; 2670b02be92SPatrick Venture } 26898a23840SMatthew Barth 2697117441cSEmily Shaffer // Fetch type from interface itself. 2707117441cSEmily Shaffer if (dbus_if.sensortype != 0) 2717117441cSEmily Shaffer { 2727117441cSEmily Shaffer type = dbus_if.sensortype; 2730b02be92SPatrick Venture } 2740b02be92SPatrick Venture else 2750b02be92SPatrick Venture { 27698a23840SMatthew Barth // Non InventoryItems 277391f3303SEmily Shaffer p = strrchr(dbus_if.path, '/'); 27856003453SBrad Bishop type = dbus_to_sensor_type(p + 1); 27998a23840SMatthew Barth } 28098a23840SMatthew Barth 28156003453SBrad Bishop return type; 28298a23840SMatthew Barth } 28398a23840SMatthew Barth 284391f3303SEmily Shaffer // Replaces find_sensor 2850b02be92SPatrick Venture uint8_t find_type_for_sensor_number(uint8_t num) 2860b02be92SPatrick Venture { 287391f3303SEmily Shaffer int r; 288391f3303SEmily Shaffer dbus_interface_t dbus_if; 2892ae09b9aSEmily Shaffer r = find_openbmc_path(num, &dbus_if); 2900b02be92SPatrick Venture if (r < 0) 2910b02be92SPatrick Venture { 292b51bf9c8SPatrick Venture std::fprintf(stderr, "Could not find sensor %d\n", num); 29391875f77SLei YU return 0; 294391f3303SEmily Shaffer } 295391f3303SEmily Shaffer return get_type_from_interface(dbus_if); 296391f3303SEmily Shaffer } 297391f3303SEmily Shaffer 29898a23840SMatthew Barth ipmi_ret_t ipmi_sen_get_sensor_type(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 2990b02be92SPatrick Venture ipmi_request_t request, 3000b02be92SPatrick Venture ipmi_response_t response, 3010b02be92SPatrick Venture ipmi_data_len_t data_len, 3020b02be92SPatrick Venture ipmi_context_t context) 30398a23840SMatthew Barth { 304d99148b3SPatrick Venture auto reqptr = static_cast<sensor_data_t*>(request); 30598a23840SMatthew Barth ipmi_ret_t rc = IPMI_CC_OK; 30698a23840SMatthew Barth 30798a23840SMatthew Barth printf("IPMI GET_SENSOR_TYPE [0x%02X]\n", reqptr->sennum); 30898a23840SMatthew Barth 30998a23840SMatthew Barth // TODO Not sure what the System-event-sensor is suppose to return 31098a23840SMatthew Barth // need to ask Hostboot team 31198a23840SMatthew Barth unsigned char buf[] = {0x00, 0x6F}; 31298a23840SMatthew Barth 313391f3303SEmily Shaffer buf[0] = find_type_for_sensor_number(reqptr->sennum); 31498a23840SMatthew Barth 31598a23840SMatthew Barth // HACK UNTIL Dbus gets updated or we find a better way 3160b02be92SPatrick Venture if (buf[0] == 0) 3170b02be92SPatrick Venture { 31898a23840SMatthew Barth rc = IPMI_CC_SENSOR_INVALID; 31998a23840SMatthew Barth } 32098a23840SMatthew Barth 32198a23840SMatthew Barth *data_len = sizeof(buf); 322b51bf9c8SPatrick Venture std::memcpy(response, &buf, *data_len); 32398a23840SMatthew Barth 32498a23840SMatthew Barth return rc; 32598a23840SMatthew Barth } 32698a23840SMatthew Barth 3270b02be92SPatrick Venture const std::set<std::string> analogSensorInterfaces = { 328cc941e15SEmily Shaffer "xyz.openbmc_project.Sensor.Value", 329e9a64056SPatrick Venture "xyz.openbmc_project.Control.FanPwm", 330cc941e15SEmily Shaffer }; 331cc941e15SEmily Shaffer 332cc941e15SEmily Shaffer bool isAnalogSensor(const std::string& interface) 333cc941e15SEmily Shaffer { 334cc941e15SEmily Shaffer return (analogSensorInterfaces.count(interface)); 335cc941e15SEmily Shaffer } 336cc941e15SEmily Shaffer 337be703f71STom Joseph ipmi_ret_t setSensorReading(void* request) 338be703f71STom Joseph { 339816e92b5STom Joseph ipmi::sensor::SetSensorReadingReq cmdData = 340816e92b5STom Joseph *(static_cast<ipmi::sensor::SetSensorReadingReq*>(request)); 341be703f71STom Joseph 342be703f71STom Joseph // Check if the Sensor Number is present 343e0af7209SDhruvaraj Subhashchandran const auto iter = sensors.find(cmdData.number); 344be703f71STom Joseph if (iter == sensors.end()) 345be703f71STom Joseph { 346be703f71STom Joseph return IPMI_CC_SENSOR_INVALID; 347be703f71STom Joseph } 348be703f71STom Joseph 34918e99992SDhruvaraj Subhashchandran try 35018e99992SDhruvaraj Subhashchandran { 3510922bde4SJayanth Othayoth if (ipmi::sensor::Mutability::Write != 3520922bde4SJayanth Othayoth (iter->second.mutability & ipmi::sensor::Mutability::Write)) 3530922bde4SJayanth Othayoth { 3540922bde4SJayanth Othayoth log<level::ERR>("Sensor Set operation is not allowed", 3550922bde4SJayanth Othayoth entry("SENSOR_NUM=%d", cmdData.number)); 3560922bde4SJayanth Othayoth return IPMI_CC_ILLEGAL_COMMAND; 3570922bde4SJayanth Othayoth } 358e0af7209SDhruvaraj Subhashchandran return iter->second.updateFunc(cmdData, iter->second); 359be703f71STom Joseph } 36018e99992SDhruvaraj Subhashchandran catch (InternalFailure& e) 36118e99992SDhruvaraj Subhashchandran { 36218e99992SDhruvaraj Subhashchandran log<level::ERR>("Set sensor failed", 36318e99992SDhruvaraj Subhashchandran entry("SENSOR_NUM=%d", cmdData.number)); 36418e99992SDhruvaraj Subhashchandran commit<InternalFailure>(); 36518e99992SDhruvaraj Subhashchandran } 3668202432fSTom Joseph catch (const std::runtime_error& e) 3678202432fSTom Joseph { 3688202432fSTom Joseph log<level::ERR>(e.what()); 3698202432fSTom Joseph } 37018e99992SDhruvaraj Subhashchandran 37118e99992SDhruvaraj Subhashchandran return IPMI_CC_UNSPECIFIED_ERROR; 37218e99992SDhruvaraj Subhashchandran } 37398a23840SMatthew Barth 37498a23840SMatthew Barth ipmi_ret_t ipmi_sen_set_sensor(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 37598a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 37698a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 37798a23840SMatthew Barth { 378d99148b3SPatrick Venture auto reqptr = static_cast<sensor_data_t*>(request); 37998a23840SMatthew Barth 3805fb14603SAditya Saripalli log<level::DEBUG>("IPMI SET_SENSOR", 3815fb14603SAditya Saripalli entry("SENSOR_NUM=0x%02x", reqptr->sennum)); 38298a23840SMatthew Barth 383be703f71STom Joseph /* 384be703f71STom Joseph * This would support the Set Sensor Reading command for the presence 385be703f71STom Joseph * and functional state of Processor, Core & DIMM. For the remaining 386be703f71STom Joseph * sensors the existing support is invoked. 387be703f71STom Joseph */ 388be703f71STom Joseph auto ipmiRC = setSensorReading(request); 389be703f71STom Joseph 390be703f71STom Joseph if (ipmiRC == IPMI_CC_SENSOR_INVALID) 391be703f71STom Joseph { 39298a23840SMatthew Barth updateSensorRecordFromSSRAESC(reqptr); 393be703f71STom Joseph ipmiRC = IPMI_CC_OK; 394be703f71STom Joseph } 39598a23840SMatthew Barth 39698a23840SMatthew Barth *data_len = 0; 397be703f71STom Joseph return ipmiRC; 39898a23840SMatthew Barth } 39998a23840SMatthew Barth 4003ee668f9STom Joseph ipmi_ret_t ipmi_sen_get_sensor_reading(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 4010b02be92SPatrick Venture ipmi_request_t request, 4020b02be92SPatrick Venture ipmi_response_t response, 4030b02be92SPatrick Venture ipmi_data_len_t data_len, 4040b02be92SPatrick Venture ipmi_context_t context) 4053ee668f9STom Joseph { 406d99148b3SPatrick Venture auto reqptr = static_cast<sensor_data_t*>(request); 407d99148b3SPatrick Venture auto resp = static_cast<sensorreadingresp_t*>(response); 4083ee668f9STom Joseph ipmi::sensor::GetSensorResponse getResponse{}; 4093ee668f9STom Joseph static constexpr auto scanningEnabledBit = 6; 4103ee668f9STom Joseph 41114c15467STom Joseph const auto iter = sensors.find(reqptr->sennum); 41214c15467STom Joseph if (iter == sensors.end()) 41314c15467STom Joseph { 414ba23ff71SAdriana Kobylak return IPMI_CC_SENSOR_INVALID; 41514c15467STom Joseph } 41613b87a3eSTom Joseph if (ipmi::sensor::Mutability::Read != 41713b87a3eSTom Joseph (iter->second.mutability & ipmi::sensor::Mutability::Read)) 41813b87a3eSTom Joseph { 4196ccf8818SJayanth Othayoth return IPMI_CC_ILLEGAL_COMMAND; 42013b87a3eSTom Joseph } 42114c15467STom Joseph 42214c15467STom Joseph try 42314c15467STom Joseph { 424c6162fb6STom Joseph getResponse = iter->second.getFunc(iter->second); 42514c15467STom Joseph *data_len = getResponse.size(); 426b51bf9c8SPatrick Venture std::memcpy(resp, getResponse.data(), *data_len); 427c6162fb6STom Joseph resp->operation = 1 << scanningEnabledBit; 42814c15467STom Joseph return IPMI_CC_OK; 42914c15467STom Joseph } 4303ee668f9STom Joseph catch (const std::exception& e) 43114c15467STom Joseph { 432c6162fb6STom Joseph *data_len = getResponse.size(); 433b51bf9c8SPatrick Venture std::memcpy(resp, getResponse.data(), *data_len); 434c6162fb6STom Joseph return IPMI_CC_OK; 43514c15467STom Joseph } 43698a23840SMatthew Barth } 43798a23840SMatthew Barth 4380ac0dd23STom Joseph void getSensorThresholds(uint8_t sensorNum, 4390ac0dd23STom Joseph get_sdr::GetSensorThresholdsResponse* response) 4400ac0dd23STom Joseph { 4410ac0dd23STom Joseph constexpr auto warningThreshIntf = 4420ac0dd23STom Joseph "xyz.openbmc_project.Sensor.Threshold.Warning"; 4430ac0dd23STom Joseph constexpr auto criticalThreshIntf = 4440ac0dd23STom Joseph "xyz.openbmc_project.Sensor.Threshold.Critical"; 4450ac0dd23STom Joseph 4460ac0dd23STom Joseph sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; 4470ac0dd23STom Joseph 4480ac0dd23STom Joseph const auto iter = sensors.find(sensorNum); 4490ac0dd23STom Joseph const auto info = iter->second; 4500ac0dd23STom Joseph 4510ac0dd23STom Joseph auto service = ipmi::getService(bus, info.sensorInterface, info.sensorPath); 4520ac0dd23STom Joseph 4530b02be92SPatrick Venture auto warnThresholds = ipmi::getAllDbusProperties( 4540b02be92SPatrick Venture bus, service, info.sensorPath, warningThreshIntf); 4550ac0dd23STom Joseph 456*37544429SJames Feist double warnLow = variant_ns::apply_visitor(ipmi::VariantToDoubleVisitor(), 4571e12112bSJames Feist warnThresholds["WarningLow"]); 458*37544429SJames Feist double warnHigh = variant_ns::apply_visitor(ipmi::VariantToDoubleVisitor(), 459*37544429SJames Feist warnThresholds["WarningHigh"]); 4600ac0dd23STom Joseph 4610ac0dd23STom Joseph if (warnLow != 0) 4620ac0dd23STom Joseph { 463586d35b4SPatrick Venture warnLow *= std::pow(10, info.scale - info.exponentR); 4640b02be92SPatrick Venture response->lowerNonCritical = static_cast<uint8_t>( 4650b02be92SPatrick Venture (warnLow - info.scaledOffset) / info.coefficientM); 4660ac0dd23STom Joseph response->validMask |= static_cast<uint8_t>( 4670ac0dd23STom Joseph ipmi::sensor::ThresholdMask::NON_CRITICAL_LOW_MASK); 4680ac0dd23STom Joseph } 4690ac0dd23STom Joseph 4700ac0dd23STom Joseph if (warnHigh != 0) 4710ac0dd23STom Joseph { 472586d35b4SPatrick Venture warnHigh *= std::pow(10, info.scale - info.exponentR); 4730b02be92SPatrick Venture response->upperNonCritical = static_cast<uint8_t>( 4740b02be92SPatrick Venture (warnHigh - info.scaledOffset) / info.coefficientM); 4750ac0dd23STom Joseph response->validMask |= static_cast<uint8_t>( 4760ac0dd23STom Joseph ipmi::sensor::ThresholdMask::NON_CRITICAL_HIGH_MASK); 4770ac0dd23STom Joseph } 4780ac0dd23STom Joseph 4790b02be92SPatrick Venture auto critThresholds = ipmi::getAllDbusProperties( 4800b02be92SPatrick Venture bus, service, info.sensorPath, criticalThreshIntf); 481*37544429SJames Feist double critLow = variant_ns::apply_visitor(ipmi::VariantToDoubleVisitor(), 4821e12112bSJames Feist critThresholds["CriticalLow"]); 483*37544429SJames Feist double critHigh = variant_ns::apply_visitor(ipmi::VariantToDoubleVisitor(), 484*37544429SJames Feist critThresholds["CriticalHigh"]); 4850ac0dd23STom Joseph 4860ac0dd23STom Joseph if (critLow != 0) 4870ac0dd23STom Joseph { 488586d35b4SPatrick Venture critLow *= std::pow(10, info.scale - info.exponentR); 4890b02be92SPatrick Venture response->lowerCritical = static_cast<uint8_t>( 4900b02be92SPatrick Venture (critLow - info.scaledOffset) / info.coefficientM); 4910ac0dd23STom Joseph response->validMask |= static_cast<uint8_t>( 4920ac0dd23STom Joseph ipmi::sensor::ThresholdMask::CRITICAL_LOW_MASK); 4930ac0dd23STom Joseph } 4940ac0dd23STom Joseph 4950ac0dd23STom Joseph if (critHigh != 0) 4960ac0dd23STom Joseph { 497586d35b4SPatrick Venture critHigh *= std::pow(10, info.scale - info.exponentR); 4980b02be92SPatrick Venture response->upperCritical = static_cast<uint8_t>( 4990b02be92SPatrick Venture (critHigh - info.scaledOffset) / info.coefficientM); 5000ac0dd23STom Joseph response->validMask |= static_cast<uint8_t>( 5010ac0dd23STom Joseph ipmi::sensor::ThresholdMask::CRITICAL_HIGH_MASK); 5020ac0dd23STom Joseph } 5030ac0dd23STom Joseph } 5040ac0dd23STom Joseph 5055c0beec1SDhruvaraj Subhashchandran ipmi_ret_t ipmi_sen_get_sensor_thresholds(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 5060b02be92SPatrick Venture ipmi_request_t request, 5070b02be92SPatrick Venture ipmi_response_t response, 5080b02be92SPatrick Venture ipmi_data_len_t data_len, 5090b02be92SPatrick Venture ipmi_context_t context) 5105c0beec1SDhruvaraj Subhashchandran { 5110ac0dd23STom Joseph constexpr auto valueInterface = "xyz.openbmc_project.Sensor.Value"; 5125c0beec1SDhruvaraj Subhashchandran 5135c0beec1SDhruvaraj Subhashchandran if (*data_len != sizeof(uint8_t)) 5145c0beec1SDhruvaraj Subhashchandran { 5150ac0dd23STom Joseph *data_len = 0; 5165c0beec1SDhruvaraj Subhashchandran return IPMI_CC_REQ_DATA_LEN_INVALID; 5175c0beec1SDhruvaraj Subhashchandran } 5185c0beec1SDhruvaraj Subhashchandran 5190ac0dd23STom Joseph auto sensorNum = *(reinterpret_cast<const uint8_t*>(request)); 5200ac0dd23STom Joseph *data_len = 0; 5215c0beec1SDhruvaraj Subhashchandran 5225c0beec1SDhruvaraj Subhashchandran const auto iter = sensors.find(sensorNum); 5235c0beec1SDhruvaraj Subhashchandran if (iter == sensors.end()) 5245c0beec1SDhruvaraj Subhashchandran { 5255c0beec1SDhruvaraj Subhashchandran return IPMI_CC_SENSOR_INVALID; 5265c0beec1SDhruvaraj Subhashchandran } 5275c0beec1SDhruvaraj Subhashchandran 5280ac0dd23STom Joseph const auto info = iter->second; 5295c0beec1SDhruvaraj Subhashchandran 5305c0beec1SDhruvaraj Subhashchandran // Proceed only if the sensor value interface is implemented. 5310ac0dd23STom Joseph if (info.propertyInterfaces.find(valueInterface) == 5320ac0dd23STom Joseph info.propertyInterfaces.end()) 5335c0beec1SDhruvaraj Subhashchandran { 5345c0beec1SDhruvaraj Subhashchandran // return with valid mask as 0 5355c0beec1SDhruvaraj Subhashchandran return IPMI_CC_OK; 5365c0beec1SDhruvaraj Subhashchandran } 5375c0beec1SDhruvaraj Subhashchandran 5380ac0dd23STom Joseph auto responseData = 5390ac0dd23STom Joseph reinterpret_cast<get_sdr::GetSensorThresholdsResponse*>(response); 5405c0beec1SDhruvaraj Subhashchandran 5415c0beec1SDhruvaraj Subhashchandran try 5425c0beec1SDhruvaraj Subhashchandran { 5430ac0dd23STom Joseph getSensorThresholds(sensorNum, responseData); 5445c0beec1SDhruvaraj Subhashchandran } 5450ac0dd23STom Joseph catch (std::exception& e) 5465c0beec1SDhruvaraj Subhashchandran { 5470ac0dd23STom Joseph // Mask if the property is not present 5485c0beec1SDhruvaraj Subhashchandran responseData->validMask = 0; 5495c0beec1SDhruvaraj Subhashchandran } 5505c0beec1SDhruvaraj Subhashchandran 5515c0beec1SDhruvaraj Subhashchandran *data_len = sizeof(get_sdr::GetSensorThresholdsResponse); 5525c0beec1SDhruvaraj Subhashchandran return IPMI_CC_OK; 5535c0beec1SDhruvaraj Subhashchandran } 5545c0beec1SDhruvaraj Subhashchandran 55598a23840SMatthew Barth ipmi_ret_t ipmi_sen_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 55698a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 55798a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 55898a23840SMatthew Barth { 55970aa8d96SNan Li ipmi_ret_t rc = IPMI_CC_INVALID; 56098a23840SMatthew Barth 56198a23840SMatthew Barth printf("IPMI S/E Wildcard Netfn:[0x%X], Cmd:[0x%X]\n", netfn, cmd); 56298a23840SMatthew Barth *data_len = 0; 56398a23840SMatthew Barth 56498a23840SMatthew Barth return rc; 56598a23840SMatthew Barth } 56698a23840SMatthew Barth 567d06e0e7eSEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 568d06e0e7eSEmily Shaffer ipmi_request_t request, 569d06e0e7eSEmily Shaffer ipmi_response_t response, 570d06e0e7eSEmily Shaffer ipmi_data_len_t data_len, 571d06e0e7eSEmily Shaffer ipmi_context_t context) 572d06e0e7eSEmily Shaffer { 573d06e0e7eSEmily Shaffer auto resp = static_cast<get_sdr_info::GetSdrInfoResp*>(response); 574d06e0e7eSEmily Shaffer if (request == nullptr || 575d06e0e7eSEmily Shaffer get_sdr_info::request::get_count(request) == false) 576d06e0e7eSEmily Shaffer { 577d06e0e7eSEmily Shaffer // Get Sensor Count 578e0cc8553SRatan Gupta resp->count = sensors.size() + frus.size(); 579d06e0e7eSEmily Shaffer } 580d06e0e7eSEmily Shaffer else 581d06e0e7eSEmily Shaffer { 582d06e0e7eSEmily Shaffer resp->count = 1; 583d06e0e7eSEmily Shaffer } 584d06e0e7eSEmily Shaffer 585d06e0e7eSEmily Shaffer // Multiple LUNs not supported. 586d06e0e7eSEmily Shaffer namespace response = get_sdr_info::response; 587d06e0e7eSEmily Shaffer response::set_lun_present(0, &(resp->luns_and_dynamic_population)); 588d06e0e7eSEmily Shaffer response::set_lun_not_present(1, &(resp->luns_and_dynamic_population)); 589d06e0e7eSEmily Shaffer response::set_lun_not_present(2, &(resp->luns_and_dynamic_population)); 590d06e0e7eSEmily Shaffer response::set_lun_not_present(3, &(resp->luns_and_dynamic_population)); 591d06e0e7eSEmily Shaffer response::set_static_population(&(resp->luns_and_dynamic_population)); 592d06e0e7eSEmily Shaffer 593d06e0e7eSEmily Shaffer *data_len = SDR_INFO_RESP_SIZE; 594d06e0e7eSEmily Shaffer 595d06e0e7eSEmily Shaffer return IPMI_CC_OK; 596d06e0e7eSEmily Shaffer } 597d06e0e7eSEmily Shaffer 598a344afc0SEmily Shaffer ipmi_ret_t ipmi_sen_reserve_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 599a344afc0SEmily Shaffer ipmi_request_t request, 600a344afc0SEmily Shaffer ipmi_response_t response, 601a344afc0SEmily Shaffer ipmi_data_len_t data_len, 602a344afc0SEmily Shaffer ipmi_context_t context) 603a344afc0SEmily Shaffer { 604a344afc0SEmily Shaffer // A constant reservation ID is okay until we implement add/remove SDR. 605a344afc0SEmily Shaffer const uint16_t reservation_id = 1; 606a344afc0SEmily Shaffer *(uint16_t*)response = reservation_id; 6075a5a6282SEmily Shaffer *data_len = sizeof(uint16_t); 608a344afc0SEmily Shaffer 609a344afc0SEmily Shaffer printf("Created new IPMI SDR reservation ID %d\n", *(uint16_t*)response); 610a344afc0SEmily Shaffer return IPMI_CC_OK; 611a344afc0SEmily Shaffer } 61298a23840SMatthew Barth 613dc212b23STom Joseph void setUnitFieldsForObject(const ipmi::sensor::Info* info, 614cc941e15SEmily Shaffer get_sdr::SensorDataFullRecordBody* body) 615bbef71c2SEmily Shaffer { 616bbef71c2SEmily Shaffer namespace server = sdbusplus::xyz::openbmc_project::Sensor::server; 617dc212b23STom Joseph try 618dc212b23STom Joseph { 619dc212b23STom Joseph auto unit = server::Value::convertUnitFromString(info->unit); 620bbef71c2SEmily Shaffer // Unit strings defined in 621bbef71c2SEmily Shaffer // phosphor-dbus-interfaces/xyz/openbmc_project/Sensor/Value.interface.yaml 622bbef71c2SEmily Shaffer switch (unit) 623bbef71c2SEmily Shaffer { 624bbef71c2SEmily Shaffer case server::Value::Unit::DegreesC: 625bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_DEGREES_C; 626bbef71c2SEmily Shaffer break; 627bbef71c2SEmily Shaffer case server::Value::Unit::RPMS: 6280b02be92SPatrick Venture body->sensor_units_2_base = 6290b02be92SPatrick Venture get_sdr::SENSOR_UNIT_REVOLUTIONS; // revolutions 630bbef71c2SEmily Shaffer get_sdr::body::set_rate_unit(0b100, body); // per minute 631bbef71c2SEmily Shaffer break; 632bbef71c2SEmily Shaffer case server::Value::Unit::Volts: 633bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_VOLTS; 634bbef71c2SEmily Shaffer break; 635bbef71c2SEmily Shaffer case server::Value::Unit::Meters: 636bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_METERS; 637bbef71c2SEmily Shaffer break; 638bbef71c2SEmily Shaffer case server::Value::Unit::Amperes: 639bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_AMPERES; 640bbef71c2SEmily Shaffer break; 641bbef71c2SEmily Shaffer case server::Value::Unit::Joules: 642bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_JOULES; 643bbef71c2SEmily Shaffer break; 644dc212b23STom Joseph case server::Value::Unit::Watts: 645dc212b23STom Joseph body->sensor_units_2_base = get_sdr::SENSOR_UNIT_WATTS; 646dc212b23STom Joseph break; 647bbef71c2SEmily Shaffer default: 648cc941e15SEmily Shaffer // Cannot be hit. 649b51bf9c8SPatrick Venture std::fprintf(stderr, "Unknown value unit type: = %s\n", 650dc212b23STom Joseph info->unit.c_str()); 651cc941e15SEmily Shaffer } 652cc941e15SEmily Shaffer } 65364678b85SPatrick Venture catch (const sdbusplus::exception::InvalidEnumString& e) 654cc941e15SEmily Shaffer { 655cc941e15SEmily Shaffer log<level::WARNING>("Warning: no unit provided for sensor!"); 656cc941e15SEmily Shaffer } 657cc941e15SEmily Shaffer } 658cc941e15SEmily Shaffer 659cc941e15SEmily Shaffer ipmi_ret_t populate_record_from_dbus(get_sdr::SensorDataFullRecordBody* body, 660cc941e15SEmily Shaffer const ipmi::sensor::Info* info, 661cc941e15SEmily Shaffer ipmi_data_len_t data_len) 662cc941e15SEmily Shaffer { 663cc941e15SEmily Shaffer /* Functional sensor case */ 664cc941e15SEmily Shaffer if (isAnalogSensor(info->propertyInterfaces.begin()->first)) 665cc941e15SEmily Shaffer { 666cc941e15SEmily Shaffer 667cc941e15SEmily Shaffer body->sensor_units_1 = 0; // unsigned, no rate, no modifier, not a % 668cc941e15SEmily Shaffer 669cc941e15SEmily Shaffer /* Unit info */ 670dc212b23STom Joseph setUnitFieldsForObject(info, body); 67110f4959aSEmily Shaffer 67210f4959aSEmily Shaffer get_sdr::body::set_b(info->coefficientB, body); 67310f4959aSEmily Shaffer get_sdr::body::set_m(info->coefficientM, body); 67410f4959aSEmily Shaffer get_sdr::body::set_b_exp(info->exponentB, body); 675dc212b23STom Joseph get_sdr::body::set_r_exp(info->exponentR, body); 676bbef71c2SEmily Shaffer 677bbef71c2SEmily Shaffer get_sdr::body::set_id_type(0b00, body); // 00 = unicode 6789642391dSTom Joseph } 6799642391dSTom Joseph 6809642391dSTom Joseph /* ID string */ 6819642391dSTom Joseph auto id_string = info->sensorNameFunc(*info); 6829642391dSTom Joseph 683bbef71c2SEmily Shaffer if (id_string.length() > FULL_RECORD_ID_STR_MAX_LENGTH) 684bbef71c2SEmily Shaffer { 685bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(FULL_RECORD_ID_STR_MAX_LENGTH, body); 686bbef71c2SEmily Shaffer } 687bbef71c2SEmily Shaffer else 688bbef71c2SEmily Shaffer { 689bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(id_string.length(), body); 690bbef71c2SEmily Shaffer } 691bbef71c2SEmily Shaffer strncpy(body->id_string, id_string.c_str(), 692bbef71c2SEmily Shaffer get_sdr::body::get_id_strlen(body)); 693bbef71c2SEmily Shaffer 694bbef71c2SEmily Shaffer return IPMI_CC_OK; 695bbef71c2SEmily Shaffer }; 696bbef71c2SEmily Shaffer 697e0cc8553SRatan Gupta ipmi_ret_t ipmi_fru_get_sdr(ipmi_request_t request, ipmi_response_t response, 698e0cc8553SRatan Gupta ipmi_data_len_t data_len) 699e0cc8553SRatan Gupta { 700e0cc8553SRatan Gupta auto req = reinterpret_cast<get_sdr::GetSdrReq*>(request); 701e0cc8553SRatan Gupta auto resp = reinterpret_cast<get_sdr::GetSdrResp*>(response); 702e0cc8553SRatan Gupta get_sdr::SensorDataFruRecord record{}; 703e0cc8553SRatan Gupta auto dataLength = 0; 704e0cc8553SRatan Gupta 705e0cc8553SRatan Gupta auto fru = frus.begin(); 706e0cc8553SRatan Gupta uint8_t fruID{}; 707e0cc8553SRatan Gupta auto recordID = get_sdr::request::get_record_id(req); 708e0cc8553SRatan Gupta 709e0cc8553SRatan Gupta fruID = recordID - FRU_RECORD_ID_START; 710e0cc8553SRatan Gupta fru = frus.find(fruID); 711e0cc8553SRatan Gupta if (fru == frus.end()) 712e0cc8553SRatan Gupta { 713e0cc8553SRatan Gupta return IPMI_CC_SENSOR_INVALID; 714e0cc8553SRatan Gupta } 715e0cc8553SRatan Gupta 716e0cc8553SRatan Gupta /* Header */ 717e0cc8553SRatan Gupta get_sdr::header::set_record_id(recordID, &(record.header)); 718e0cc8553SRatan Gupta record.header.sdr_version = SDR_VERSION; // Based on IPMI Spec v2.0 rev 1.1 719e0cc8553SRatan Gupta record.header.record_type = get_sdr::SENSOR_DATA_FRU_RECORD; 720e0cc8553SRatan Gupta record.header.record_length = sizeof(record.key) + sizeof(record.body); 721e0cc8553SRatan Gupta 722e0cc8553SRatan Gupta /* Key */ 723e0cc8553SRatan Gupta record.key.fruID = fruID; 724e0cc8553SRatan Gupta record.key.accessLun |= IPMI_LOGICAL_FRU; 725e0cc8553SRatan Gupta record.key.deviceAddress = BMCSlaveAddress; 726e0cc8553SRatan Gupta 727e0cc8553SRatan Gupta /* Body */ 728e0cc8553SRatan Gupta record.body.entityID = fru->second[0].entityID; 729e0cc8553SRatan Gupta record.body.entityInstance = fru->second[0].entityInstance; 730e0cc8553SRatan Gupta record.body.deviceType = fruInventoryDevice; 731e0cc8553SRatan Gupta record.body.deviceTypeModifier = IPMIFruInventory; 732e0cc8553SRatan Gupta 733e0cc8553SRatan Gupta /* Device ID string */ 7340b02be92SPatrick Venture auto deviceID = 7350b02be92SPatrick Venture fru->second[0].path.substr(fru->second[0].path.find_last_of('/') + 1, 736e0cc8553SRatan Gupta fru->second[0].path.length()); 737e0cc8553SRatan Gupta 738e0cc8553SRatan Gupta if (deviceID.length() > get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH) 739e0cc8553SRatan Gupta { 740e0cc8553SRatan Gupta get_sdr::body::set_device_id_strlen( 7410b02be92SPatrick Venture get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH, &(record.body)); 742e0cc8553SRatan Gupta } 743e0cc8553SRatan Gupta else 744e0cc8553SRatan Gupta { 7450b02be92SPatrick Venture get_sdr::body::set_device_id_strlen(deviceID.length(), &(record.body)); 746e0cc8553SRatan Gupta } 747e0cc8553SRatan Gupta 748e0cc8553SRatan Gupta strncpy(record.body.deviceID, deviceID.c_str(), 749e0cc8553SRatan Gupta get_sdr::body::get_device_id_strlen(&(record.body))); 750e0cc8553SRatan Gupta 751e0cc8553SRatan Gupta if (++fru == frus.end()) 752e0cc8553SRatan Gupta { 7530b02be92SPatrick Venture get_sdr::response::set_next_record_id(END_OF_RECORD, 7540b02be92SPatrick Venture resp); // last record 755e0cc8553SRatan Gupta } 756e0cc8553SRatan Gupta else 757e0cc8553SRatan Gupta { 758e0cc8553SRatan Gupta get_sdr::response::set_next_record_id( 759e0cc8553SRatan Gupta (FRU_RECORD_ID_START + fru->first), resp); 760e0cc8553SRatan Gupta } 761e0cc8553SRatan Gupta 7620fbdbce2SEmily Shaffer // Check for invalid offset size 7630fbdbce2SEmily Shaffer if (req->offset > sizeof(record)) 764e0cc8553SRatan Gupta { 7650fbdbce2SEmily Shaffer return IPMI_CC_PARM_OUT_OF_RANGE; 766e0cc8553SRatan Gupta } 767e0cc8553SRatan Gupta 7680fbdbce2SEmily Shaffer dataLength = std::min(static_cast<size_t>(req->bytes_to_read), 7690fbdbce2SEmily Shaffer sizeof(record) - req->offset); 770e0cc8553SRatan Gupta 771b51bf9c8SPatrick Venture std::memcpy(resp->record_data, 7721cd85963SJason M. Bills reinterpret_cast<uint8_t*>(&record) + req->offset, dataLength); 773e0cc8553SRatan Gupta 774e0cc8553SRatan Gupta *data_len = dataLength; 775e0cc8553SRatan Gupta *data_len += 2; // additional 2 bytes for next record ID 776e0cc8553SRatan Gupta 777e0cc8553SRatan Gupta return IPMI_CC_OK; 778e0cc8553SRatan Gupta } 779e0cc8553SRatan Gupta 780bbef71c2SEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 781bbef71c2SEmily Shaffer ipmi_request_t request, ipmi_response_t response, 782bbef71c2SEmily Shaffer ipmi_data_len_t data_len, ipmi_context_t context) 783bbef71c2SEmily Shaffer { 784bbef71c2SEmily Shaffer ipmi_ret_t ret = IPMI_CC_OK; 785bbef71c2SEmily Shaffer get_sdr::GetSdrReq* req = (get_sdr::GetSdrReq*)request; 786bbef71c2SEmily Shaffer get_sdr::GetSdrResp* resp = (get_sdr::GetSdrResp*)response; 787bbef71c2SEmily Shaffer get_sdr::SensorDataFullRecord record = {0}; 788bbef71c2SEmily Shaffer if (req != NULL) 789bbef71c2SEmily Shaffer { 790bbef71c2SEmily Shaffer // Note: we use an iterator so we can provide the next ID at the end of 791bbef71c2SEmily Shaffer // the call. 792bbef71c2SEmily Shaffer auto sensor = sensors.begin(); 793e0cc8553SRatan Gupta auto recordID = get_sdr::request::get_record_id(req); 794bbef71c2SEmily Shaffer 795bbef71c2SEmily Shaffer // At the beginning of a scan, the host side will send us id=0. 796e0cc8553SRatan Gupta if (recordID != 0) 797bbef71c2SEmily Shaffer { 798e0cc8553SRatan Gupta // recordID greater then 255,it means it is a FRU record. 799e0cc8553SRatan Gupta // Currently we are supporting two record types either FULL record 800e0cc8553SRatan Gupta // or FRU record. 801e0cc8553SRatan Gupta if (recordID >= FRU_RECORD_ID_START) 802e0cc8553SRatan Gupta { 803e0cc8553SRatan Gupta return ipmi_fru_get_sdr(request, response, data_len); 804e0cc8553SRatan Gupta } 805e0cc8553SRatan Gupta else 806e0cc8553SRatan Gupta { 807e0cc8553SRatan Gupta sensor = sensors.find(recordID); 808e0cc8553SRatan Gupta if (sensor == sensors.end()) 809e0cc8553SRatan Gupta { 810bbef71c2SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 811bbef71c2SEmily Shaffer } 812bbef71c2SEmily Shaffer } 813e0cc8553SRatan Gupta } 814bbef71c2SEmily Shaffer 815bbef71c2SEmily Shaffer uint8_t sensor_id = sensor->first; 816bbef71c2SEmily Shaffer 817bbef71c2SEmily Shaffer /* Header */ 818bbef71c2SEmily Shaffer get_sdr::header::set_record_id(sensor_id, &(record.header)); 819bbef71c2SEmily Shaffer record.header.sdr_version = 0x51; // Based on IPMI Spec v2.0 rev 1.1 820bbef71c2SEmily Shaffer record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD; 821bbef71c2SEmily Shaffer record.header.record_length = sizeof(get_sdr::SensorDataFullRecord); 822bbef71c2SEmily Shaffer 823bbef71c2SEmily Shaffer /* Key */ 8249642391dSTom Joseph get_sdr::key::set_owner_id_bmc(&(record.key)); 825bbef71c2SEmily Shaffer record.key.sensor_number = sensor_id; 826bbef71c2SEmily Shaffer 827bbef71c2SEmily Shaffer /* Body */ 8289642391dSTom Joseph record.body.entity_id = sensor->second.entityType; 829bbef71c2SEmily Shaffer record.body.sensor_type = sensor->second.sensorType; 830bbef71c2SEmily Shaffer record.body.event_reading_type = sensor->second.sensorReadingType; 8319642391dSTom Joseph record.body.entity_instance = sensor->second.instance; 832bbef71c2SEmily Shaffer 833bbef71c2SEmily Shaffer // Set the type-specific details given the DBus interface 834bbef71c2SEmily Shaffer ret = populate_record_from_dbus(&(record.body), &(sensor->second), 835bbef71c2SEmily Shaffer data_len); 836bbef71c2SEmily Shaffer 837bbef71c2SEmily Shaffer if (++sensor == sensors.end()) 838bbef71c2SEmily Shaffer { 839e0cc8553SRatan Gupta // we have reached till end of sensor, so assign the next record id 840e0cc8553SRatan Gupta // to 256(Max Sensor ID = 255) + FRU ID(may start with 0). 8410b02be92SPatrick Venture auto next_record_id = 8420b02be92SPatrick Venture (frus.size()) ? frus.begin()->first + FRU_RECORD_ID_START 8430b02be92SPatrick Venture : END_OF_RECORD; 844e0cc8553SRatan Gupta 845e0cc8553SRatan Gupta get_sdr::response::set_next_record_id(next_record_id, resp); 846bbef71c2SEmily Shaffer } 847bbef71c2SEmily Shaffer else 848bbef71c2SEmily Shaffer { 849bbef71c2SEmily Shaffer get_sdr::response::set_next_record_id(sensor->first, resp); 850bbef71c2SEmily Shaffer } 851bbef71c2SEmily Shaffer 8526c9ee519SEmily Shaffer if (req->offset > sizeof(record)) 8536c9ee519SEmily Shaffer { 8546c9ee519SEmily Shaffer return IPMI_CC_PARM_OUT_OF_RANGE; 8556c9ee519SEmily Shaffer } 8566c9ee519SEmily Shaffer 8576c9ee519SEmily Shaffer // data_len will ultimately be the size of the record, plus 8586c9ee519SEmily Shaffer // the size of the next record ID: 8596c9ee519SEmily Shaffer *data_len = std::min(static_cast<size_t>(req->bytes_to_read), 8606c9ee519SEmily Shaffer sizeof(record) - req->offset); 8616c9ee519SEmily Shaffer 8626c9ee519SEmily Shaffer std::memcpy(resp->record_data, 8636c9ee519SEmily Shaffer reinterpret_cast<uint8_t*>(&record) + req->offset, 8646c9ee519SEmily Shaffer *data_len); 8656c9ee519SEmily Shaffer 8666c9ee519SEmily Shaffer // data_len should include the LSB and MSB: 8671cd85963SJason M. Bills *data_len += 8681cd85963SJason M. Bills sizeof(resp->next_record_id_lsb) + sizeof(resp->next_record_id_msb); 869bbef71c2SEmily Shaffer } 870bbef71c2SEmily Shaffer 871bbef71c2SEmily Shaffer return ret; 872bbef71c2SEmily Shaffer } 873bbef71c2SEmily Shaffer 87498a23840SMatthew Barth void register_netfn_sen_functions() 87598a23840SMatthew Barth { 8760573237fSTom // <Wildcard Command> 8770b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_WILDCARD, nullptr, 8780b02be92SPatrick Venture ipmi_sen_wildcard, PRIVILEGE_USER); 87998a23840SMatthew Barth 8800573237fSTom // <Get Sensor Type> 8810b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE, nullptr, 8820b02be92SPatrick Venture ipmi_sen_get_sensor_type, PRIVILEGE_USER); 88398a23840SMatthew Barth 8840573237fSTom // <Set Sensor Reading and Event Status> 8850b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_SET_SENSOR, nullptr, 8860b02be92SPatrick Venture ipmi_sen_set_sensor, PRIVILEGE_OPERATOR); 88798a23840SMatthew Barth 8880573237fSTom // <Get Sensor Reading> 8890b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING, nullptr, 8900b02be92SPatrick Venture ipmi_sen_get_sensor_reading, PRIVILEGE_USER); 891a344afc0SEmily Shaffer 8925ca50959STom Joseph // <Reserve Device SDR Repository> 8935ca50959STom Joseph ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_RESERVE_DEVICE_SDR_REPO, 8940b02be92SPatrick Venture nullptr, ipmi_sen_reserve_sdr, PRIVILEGE_USER); 89598a23840SMatthew Barth 8965ca50959STom Joseph // <Get Device SDR Info> 8970b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_DEVICE_SDR_INFO, nullptr, 8980b02be92SPatrick Venture ipmi_sen_get_sdr_info, PRIVILEGE_USER); 899bbef71c2SEmily Shaffer 9005ca50959STom Joseph // <Get Device SDR> 9010b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_DEVICE_SDR, nullptr, 9020b02be92SPatrick Venture ipmi_sen_get_sdr, PRIVILEGE_USER); 903bbef71c2SEmily Shaffer 9045c0beec1SDhruvaraj Subhashchandran // <Get Sensor Thresholds> 9055c0beec1SDhruvaraj Subhashchandran ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_THRESHOLDS, 9065c0beec1SDhruvaraj Subhashchandran nullptr, ipmi_sen_get_sensor_thresholds, 9075c0beec1SDhruvaraj Subhashchandran PRIVILEGE_USER); 9085c0beec1SDhruvaraj Subhashchandran 90998a23840SMatthew Barth return; 91098a23840SMatthew Barth } 911