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> 174c008028SWilliam A. Kennington III #include <sdbusplus/message/types.hpp> 180b02be92SPatrick Venture #include <set> 190b02be92SPatrick Venture #include <xyz/openbmc_project/Common/error.hpp> 200b02be92SPatrick Venture #include <xyz/openbmc_project/Sensor/Value/server.hpp> 210b02be92SPatrick Venture 22e0cc8553SRatan Gupta static constexpr uint8_t fruInventoryDevice = 0x10; 23e0cc8553SRatan Gupta static constexpr uint8_t IPMIFruInventory = 0x02; 24e0cc8553SRatan Gupta static constexpr uint8_t BMCSlaveAddress = 0x20; 25e0cc8553SRatan Gupta 2698a23840SMatthew Barth extern int updateSensorRecordFromSSRAESC(const void*); 27d700e76aSTom extern sd_bus* bus; 28be703f71STom Joseph extern const ipmi::sensor::IdInfoMap sensors; 29e0cc8553SRatan Gupta extern const FruMap frus; 30e0cc8553SRatan Gupta 31be703f71STom Joseph using namespace phosphor::logging; 3218e99992SDhruvaraj Subhashchandran using InternalFailure = 3318e99992SDhruvaraj Subhashchandran sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 3498a23840SMatthew Barth 3537544429SJames Feist namespace variant_ns = sdbusplus::message::variant_ns; 3637544429SJames Feist 3798a23840SMatthew Barth void register_netfn_sen_functions() __attribute__((constructor)); 3898a23840SMatthew Barth 390b02be92SPatrick Venture struct sensorTypemap_t 400b02be92SPatrick Venture { 4198a23840SMatthew Barth uint8_t number; 4298a23840SMatthew Barth uint8_t typecode; 4398a23840SMatthew Barth char dbusname[32]; 4498a23840SMatthew Barth }; 4598a23840SMatthew Barth 4698a23840SMatthew Barth sensorTypemap_t g_SensorTypeMap[] = { 4798a23840SMatthew Barth 4898a23840SMatthew Barth {0x01, 0x6F, "Temp"}, 4998a23840SMatthew Barth {0x0C, 0x6F, "DIMM"}, 5098a23840SMatthew Barth {0x0C, 0x6F, "MEMORY_BUFFER"}, 5198a23840SMatthew Barth {0x07, 0x6F, "PROC"}, 5298a23840SMatthew Barth {0x07, 0x6F, "CORE"}, 5398a23840SMatthew Barth {0x07, 0x6F, "CPU"}, 5498a23840SMatthew Barth {0x0F, 0x6F, "BootProgress"}, 550b02be92SPatrick Venture {0xe9, 0x09, "OccStatus"}, // E9 is an internal mapping to handle sensor 560b02be92SPatrick Venture // type code os 0x09 5798a23840SMatthew Barth {0xC3, 0x6F, "BootCount"}, 5898a23840SMatthew Barth {0x1F, 0x6F, "OperatingSystemStatus"}, 5998a23840SMatthew Barth {0x12, 0x6F, "SYSTEM_EVENT"}, 6098a23840SMatthew Barth {0xC7, 0x03, "SYSTEM"}, 6198a23840SMatthew Barth {0xC7, 0x03, "MAIN_PLANAR"}, 6298a23840SMatthew Barth {0xC2, 0x6F, "PowerCap"}, 63558184eaSTom Joseph {0x0b, 0xCA, "PowerSupplyRedundancy"}, 640661beb1SJayanth Othayoth {0xDA, 0x03, "TurboAllowed"}, 65558184eaSTom Joseph {0xD8, 0xC8, "PowerSupplyDerating"}, 6698a23840SMatthew Barth {0xFF, 0x00, ""}, 6798a23840SMatthew Barth }; 6898a23840SMatthew Barth 690b02be92SPatrick Venture struct sensor_data_t 700b02be92SPatrick Venture { 7198a23840SMatthew Barth uint8_t sennum; 7298a23840SMatthew Barth } __attribute__((packed)); 7398a23840SMatthew Barth 740b02be92SPatrick Venture struct sensorreadingresp_t 750b02be92SPatrick Venture { 7698a23840SMatthew Barth uint8_t value; 7798a23840SMatthew Barth uint8_t operation; 7898a23840SMatthew Barth uint8_t indication[2]; 7998a23840SMatthew Barth } __attribute__((packed)); 8098a23840SMatthew Barth 810b02be92SPatrick Venture int get_bus_for_path(const char* path, char** busname) 820b02be92SPatrick Venture { 832ae09b9aSEmily Shaffer return mapper_get_service(bus, path, busname); 842ae09b9aSEmily Shaffer } 85d700e76aSTom 862ae09b9aSEmily Shaffer // Use a lookup table to find the interface name of a specific sensor 872ae09b9aSEmily Shaffer // This will be used until an alternative is found. this is the first 882ae09b9aSEmily Shaffer // step for mapping IPMI 890b02be92SPatrick Venture int find_openbmc_path(uint8_t num, dbus_interface_t* interface) 900b02be92SPatrick Venture { 912ae09b9aSEmily Shaffer int rc; 922ae09b9aSEmily Shaffer 932ae09b9aSEmily Shaffer const auto& sensor_it = sensors.find(num); 942ae09b9aSEmily Shaffer if (sensor_it == sensors.end()) 952ae09b9aSEmily Shaffer { 96ba23ff71SAdriana Kobylak // The sensor map does not contain the sensor requested 97ba23ff71SAdriana Kobylak return -EINVAL; 982ae09b9aSEmily Shaffer } 992ae09b9aSEmily Shaffer 1002ae09b9aSEmily Shaffer const auto& info = sensor_it->second; 1012ae09b9aSEmily Shaffer 1028451edf5SPatrick Williams char* busname = nullptr; 1032ae09b9aSEmily Shaffer rc = get_bus_for_path(info.sensorPath.c_str(), &busname); 1040b02be92SPatrick Venture if (rc < 0) 1050b02be92SPatrick Venture { 106b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to get %s busname: %s\n", 1070b02be92SPatrick Venture info.sensorPath.c_str(), busname); 1082ae09b9aSEmily Shaffer goto final; 1092ae09b9aSEmily Shaffer } 1102ae09b9aSEmily Shaffer 1112ae09b9aSEmily Shaffer interface->sensortype = info.sensorType; 1122ae09b9aSEmily Shaffer strcpy(interface->bus, busname); 1132ae09b9aSEmily Shaffer strcpy(interface->path, info.sensorPath.c_str()); 1142ae09b9aSEmily Shaffer // Take the interface name from the beginning of the DbusInterfaceMap. This 1152ae09b9aSEmily Shaffer // works for the Value interface but may not suffice for more complex 1162ae09b9aSEmily Shaffer // sensors. 1172ae09b9aSEmily Shaffer // tracked https://github.com/openbmc/phosphor-host-ipmid/issues/103 1180b02be92SPatrick Venture strcpy(interface->interface, 1190b02be92SPatrick Venture info.propertyInterfaces.begin()->first.c_str()); 1202ae09b9aSEmily Shaffer interface->sensornumber = num; 1212ae09b9aSEmily Shaffer 1222ae09b9aSEmily Shaffer final: 1232ae09b9aSEmily Shaffer free(busname); 1242ae09b9aSEmily Shaffer return rc; 1252ae09b9aSEmily Shaffer } 1262ae09b9aSEmily Shaffer 127d700e76aSTom ///////////////////////////////////////////////////////////////////// 128d700e76aSTom // 129d700e76aSTom // Routines used by ipmi commands wanting to interact on the dbus 130d700e76aSTom // 131d700e76aSTom ///////////////////////////////////////////////////////////////////// 1320b02be92SPatrick Venture int set_sensor_dbus_state_s(uint8_t number, const char* method, 1330b02be92SPatrick Venture const char* value) 1340b02be92SPatrick Venture { 135d700e76aSTom 136d700e76aSTom dbus_interface_t a; 137d700e76aSTom int r; 138d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 139d700e76aSTom sd_bus_message* m = NULL; 140d700e76aSTom 141b51bf9c8SPatrick Venture std::fprintf(ipmidbus, 1420b02be92SPatrick Venture "Attempting to set a dbus Variant Sensor 0x%02x via %s with a " 1430b02be92SPatrick Venture "value of %s\n", 144d700e76aSTom number, method, value); 145d700e76aSTom 1462ae09b9aSEmily Shaffer r = find_openbmc_path(number, &a); 147d700e76aSTom 1480b02be92SPatrick Venture if (r < 0) 1490b02be92SPatrick Venture { 150b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); 151d700e76aSTom return 0; 152d700e76aSTom } 153d700e76aSTom 1540b02be92SPatrick Venture r = sd_bus_message_new_method_call(bus, &m, a.bus, a.path, a.interface, 1550b02be92SPatrick Venture method); 1560b02be92SPatrick Venture if (r < 0) 1570b02be92SPatrick Venture { 158b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a method call: %s", 159b51bf9c8SPatrick Venture strerror(-r)); 160d700e76aSTom goto final; 161d700e76aSTom } 162d700e76aSTom 163d700e76aSTom r = sd_bus_message_append(m, "v", "s", value); 1640b02be92SPatrick Venture if (r < 0) 1650b02be92SPatrick Venture { 166b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a input parameter: %s", 167b51bf9c8SPatrick Venture strerror(-r)); 168d700e76aSTom goto final; 169d700e76aSTom } 170d700e76aSTom 171d700e76aSTom r = sd_bus_call(bus, m, 0, &error, NULL); 1720b02be92SPatrick Venture if (r < 0) 1730b02be92SPatrick Venture { 174b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to call the method: %s", strerror(-r)); 175d700e76aSTom } 176d700e76aSTom 177d700e76aSTom final: 178d700e76aSTom sd_bus_error_free(&error); 179d700e76aSTom m = sd_bus_message_unref(m); 180d700e76aSTom 181d700e76aSTom return 0; 182d700e76aSTom } 1830b02be92SPatrick Venture int set_sensor_dbus_state_y(uint8_t number, const char* method, 1840b02be92SPatrick Venture const uint8_t value) 1850b02be92SPatrick Venture { 186d700e76aSTom 187d700e76aSTom dbus_interface_t a; 188d700e76aSTom int r; 189d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 190d700e76aSTom sd_bus_message* m = NULL; 191d700e76aSTom 192b51bf9c8SPatrick Venture std::fprintf(ipmidbus, 1930b02be92SPatrick Venture "Attempting to set a dbus Variant Sensor 0x%02x via %s with a " 1940b02be92SPatrick Venture "value of 0x%02x\n", 195d700e76aSTom number, method, value); 196d700e76aSTom 1972ae09b9aSEmily Shaffer r = find_openbmc_path(number, &a); 198d700e76aSTom 1990b02be92SPatrick Venture if (r < 0) 2000b02be92SPatrick Venture { 201b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); 202d700e76aSTom return 0; 203d700e76aSTom } 204d700e76aSTom 2050b02be92SPatrick Venture r = sd_bus_message_new_method_call(bus, &m, a.bus, a.path, a.interface, 2060b02be92SPatrick Venture method); 2070b02be92SPatrick Venture if (r < 0) 2080b02be92SPatrick Venture { 209b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a method call: %s", 210b51bf9c8SPatrick Venture strerror(-r)); 211d700e76aSTom goto final; 212d700e76aSTom } 213d700e76aSTom 214d700e76aSTom r = sd_bus_message_append(m, "v", "i", value); 2150b02be92SPatrick Venture if (r < 0) 2160b02be92SPatrick Venture { 217b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a input parameter: %s", 218b51bf9c8SPatrick Venture strerror(-r)); 219d700e76aSTom goto final; 220d700e76aSTom } 221d700e76aSTom 222d700e76aSTom r = sd_bus_call(bus, m, 0, &error, NULL); 2230b02be92SPatrick Venture if (r < 0) 2240b02be92SPatrick Venture { 225b51bf9c8SPatrick Venture std::fprintf(stderr, "12 Failed to call the method: %s", strerror(-r)); 226d700e76aSTom } 227d700e76aSTom 228d700e76aSTom final: 229d700e76aSTom sd_bus_error_free(&error); 230d700e76aSTom m = sd_bus_message_unref(m); 231d700e76aSTom 232d700e76aSTom return 0; 233d700e76aSTom } 234d700e76aSTom 2350b02be92SPatrick Venture uint8_t dbus_to_sensor_type(char* p) 2360b02be92SPatrick Venture { 23798a23840SMatthew Barth 23898a23840SMatthew Barth sensorTypemap_t* s = g_SensorTypeMap; 23998a23840SMatthew Barth char r = 0; 2400b02be92SPatrick Venture while (s->number != 0xFF) 2410b02be92SPatrick Venture { 2420b02be92SPatrick Venture if (!strcmp(s->dbusname, p)) 2430b02be92SPatrick Venture { 244558184eaSTom Joseph r = s->typecode; 24598a23840SMatthew Barth break; 24698a23840SMatthew Barth } 24798a23840SMatthew Barth s++; 24898a23840SMatthew Barth } 24998a23840SMatthew Barth 25098a23840SMatthew Barth if (s->number == 0xFF) 25198a23840SMatthew Barth printf("Failed to find Sensor Type %s\n", p); 25298a23840SMatthew Barth 25398a23840SMatthew Barth return r; 25498a23840SMatthew Barth } 25598a23840SMatthew Barth 2560b02be92SPatrick Venture uint8_t get_type_from_interface(dbus_interface_t dbus_if) 2570b02be92SPatrick Venture { 25898a23840SMatthew Barth 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 2774491a46fSPatrick Venture char* 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 4564c008028SWilliam A. Kennington III double warnLow = variant_ns::visit(ipmi::VariantToDoubleVisitor(), 4571e12112bSJames Feist warnThresholds["WarningLow"]); 4584c008028SWilliam A. Kennington III double warnHigh = variant_ns::visit(ipmi::VariantToDoubleVisitor(), 45937544429SJames 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); 4814c008028SWilliam A. Kennington III double critLow = variant_ns::visit(ipmi::VariantToDoubleVisitor(), 4821e12112bSJames Feist critThresholds["CriticalLow"]); 4834c008028SWilliam A. Kennington III double critHigh = variant_ns::visit(ipmi::VariantToDoubleVisitor(), 48437544429SJames 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: 628*812e44c7SKirill Pakhomov body->sensor_units_2_base = get_sdr::SENSOR_UNIT_RPM; 629bbef71c2SEmily Shaffer break; 630bbef71c2SEmily Shaffer case server::Value::Unit::Volts: 631bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_VOLTS; 632bbef71c2SEmily Shaffer break; 633bbef71c2SEmily Shaffer case server::Value::Unit::Meters: 634bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_METERS; 635bbef71c2SEmily Shaffer break; 636bbef71c2SEmily Shaffer case server::Value::Unit::Amperes: 637bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_AMPERES; 638bbef71c2SEmily Shaffer break; 639bbef71c2SEmily Shaffer case server::Value::Unit::Joules: 640bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_JOULES; 641bbef71c2SEmily Shaffer break; 642dc212b23STom Joseph case server::Value::Unit::Watts: 643dc212b23STom Joseph body->sensor_units_2_base = get_sdr::SENSOR_UNIT_WATTS; 644dc212b23STom Joseph break; 645bbef71c2SEmily Shaffer default: 646cc941e15SEmily Shaffer // Cannot be hit. 647b51bf9c8SPatrick Venture std::fprintf(stderr, "Unknown value unit type: = %s\n", 648dc212b23STom Joseph info->unit.c_str()); 649cc941e15SEmily Shaffer } 650cc941e15SEmily Shaffer } 65164678b85SPatrick Venture catch (const sdbusplus::exception::InvalidEnumString& e) 652cc941e15SEmily Shaffer { 653cc941e15SEmily Shaffer log<level::WARNING>("Warning: no unit provided for sensor!"); 654cc941e15SEmily Shaffer } 655cc941e15SEmily Shaffer } 656cc941e15SEmily Shaffer 657cc941e15SEmily Shaffer ipmi_ret_t populate_record_from_dbus(get_sdr::SensorDataFullRecordBody* body, 658cc941e15SEmily Shaffer const ipmi::sensor::Info* info, 659cc941e15SEmily Shaffer ipmi_data_len_t data_len) 660cc941e15SEmily Shaffer { 661cc941e15SEmily Shaffer /* Functional sensor case */ 662cc941e15SEmily Shaffer if (isAnalogSensor(info->propertyInterfaces.begin()->first)) 663cc941e15SEmily Shaffer { 664cc941e15SEmily Shaffer 665cc941e15SEmily Shaffer body->sensor_units_1 = 0; // unsigned, no rate, no modifier, not a % 666cc941e15SEmily Shaffer 667cc941e15SEmily Shaffer /* Unit info */ 668dc212b23STom Joseph setUnitFieldsForObject(info, body); 66910f4959aSEmily Shaffer 67010f4959aSEmily Shaffer get_sdr::body::set_b(info->coefficientB, body); 67110f4959aSEmily Shaffer get_sdr::body::set_m(info->coefficientM, body); 67210f4959aSEmily Shaffer get_sdr::body::set_b_exp(info->exponentB, body); 673dc212b23STom Joseph get_sdr::body::set_r_exp(info->exponentR, body); 674bbef71c2SEmily Shaffer 675bbef71c2SEmily Shaffer get_sdr::body::set_id_type(0b00, body); // 00 = unicode 6769642391dSTom Joseph } 6779642391dSTom Joseph 6789642391dSTom Joseph /* ID string */ 6799642391dSTom Joseph auto id_string = info->sensorNameFunc(*info); 6809642391dSTom Joseph 681bbef71c2SEmily Shaffer if (id_string.length() > FULL_RECORD_ID_STR_MAX_LENGTH) 682bbef71c2SEmily Shaffer { 683bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(FULL_RECORD_ID_STR_MAX_LENGTH, body); 684bbef71c2SEmily Shaffer } 685bbef71c2SEmily Shaffer else 686bbef71c2SEmily Shaffer { 687bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(id_string.length(), body); 688bbef71c2SEmily Shaffer } 689bbef71c2SEmily Shaffer strncpy(body->id_string, id_string.c_str(), 690bbef71c2SEmily Shaffer get_sdr::body::get_id_strlen(body)); 691bbef71c2SEmily Shaffer 692bbef71c2SEmily Shaffer return IPMI_CC_OK; 693bbef71c2SEmily Shaffer }; 694bbef71c2SEmily Shaffer 695e0cc8553SRatan Gupta ipmi_ret_t ipmi_fru_get_sdr(ipmi_request_t request, ipmi_response_t response, 696e0cc8553SRatan Gupta ipmi_data_len_t data_len) 697e0cc8553SRatan Gupta { 698e0cc8553SRatan Gupta auto req = reinterpret_cast<get_sdr::GetSdrReq*>(request); 699e0cc8553SRatan Gupta auto resp = reinterpret_cast<get_sdr::GetSdrResp*>(response); 700e0cc8553SRatan Gupta get_sdr::SensorDataFruRecord record{}; 701e0cc8553SRatan Gupta auto dataLength = 0; 702e0cc8553SRatan Gupta 703e0cc8553SRatan Gupta auto fru = frus.begin(); 704e0cc8553SRatan Gupta uint8_t fruID{}; 705e0cc8553SRatan Gupta auto recordID = get_sdr::request::get_record_id(req); 706e0cc8553SRatan Gupta 707e0cc8553SRatan Gupta fruID = recordID - FRU_RECORD_ID_START; 708e0cc8553SRatan Gupta fru = frus.find(fruID); 709e0cc8553SRatan Gupta if (fru == frus.end()) 710e0cc8553SRatan Gupta { 711e0cc8553SRatan Gupta return IPMI_CC_SENSOR_INVALID; 712e0cc8553SRatan Gupta } 713e0cc8553SRatan Gupta 714e0cc8553SRatan Gupta /* Header */ 715e0cc8553SRatan Gupta get_sdr::header::set_record_id(recordID, &(record.header)); 716e0cc8553SRatan Gupta record.header.sdr_version = SDR_VERSION; // Based on IPMI Spec v2.0 rev 1.1 717e0cc8553SRatan Gupta record.header.record_type = get_sdr::SENSOR_DATA_FRU_RECORD; 718e0cc8553SRatan Gupta record.header.record_length = sizeof(record.key) + sizeof(record.body); 719e0cc8553SRatan Gupta 720e0cc8553SRatan Gupta /* Key */ 721e0cc8553SRatan Gupta record.key.fruID = fruID; 722e0cc8553SRatan Gupta record.key.accessLun |= IPMI_LOGICAL_FRU; 723e0cc8553SRatan Gupta record.key.deviceAddress = BMCSlaveAddress; 724e0cc8553SRatan Gupta 725e0cc8553SRatan Gupta /* Body */ 726e0cc8553SRatan Gupta record.body.entityID = fru->second[0].entityID; 727e0cc8553SRatan Gupta record.body.entityInstance = fru->second[0].entityInstance; 728e0cc8553SRatan Gupta record.body.deviceType = fruInventoryDevice; 729e0cc8553SRatan Gupta record.body.deviceTypeModifier = IPMIFruInventory; 730e0cc8553SRatan Gupta 731e0cc8553SRatan Gupta /* Device ID string */ 7320b02be92SPatrick Venture auto deviceID = 7330b02be92SPatrick Venture fru->second[0].path.substr(fru->second[0].path.find_last_of('/') + 1, 734e0cc8553SRatan Gupta fru->second[0].path.length()); 735e0cc8553SRatan Gupta 736e0cc8553SRatan Gupta if (deviceID.length() > get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH) 737e0cc8553SRatan Gupta { 738e0cc8553SRatan Gupta get_sdr::body::set_device_id_strlen( 7390b02be92SPatrick Venture get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH, &(record.body)); 740e0cc8553SRatan Gupta } 741e0cc8553SRatan Gupta else 742e0cc8553SRatan Gupta { 7430b02be92SPatrick Venture get_sdr::body::set_device_id_strlen(deviceID.length(), &(record.body)); 744e0cc8553SRatan Gupta } 745e0cc8553SRatan Gupta 746e0cc8553SRatan Gupta strncpy(record.body.deviceID, deviceID.c_str(), 747e0cc8553SRatan Gupta get_sdr::body::get_device_id_strlen(&(record.body))); 748e0cc8553SRatan Gupta 749e0cc8553SRatan Gupta if (++fru == frus.end()) 750e0cc8553SRatan Gupta { 7510b02be92SPatrick Venture get_sdr::response::set_next_record_id(END_OF_RECORD, 7520b02be92SPatrick Venture resp); // last record 753e0cc8553SRatan Gupta } 754e0cc8553SRatan Gupta else 755e0cc8553SRatan Gupta { 756e0cc8553SRatan Gupta get_sdr::response::set_next_record_id( 757e0cc8553SRatan Gupta (FRU_RECORD_ID_START + fru->first), resp); 758e0cc8553SRatan Gupta } 759e0cc8553SRatan Gupta 7600fbdbce2SEmily Shaffer // Check for invalid offset size 7610fbdbce2SEmily Shaffer if (req->offset > sizeof(record)) 762e0cc8553SRatan Gupta { 7630fbdbce2SEmily Shaffer return IPMI_CC_PARM_OUT_OF_RANGE; 764e0cc8553SRatan Gupta } 765e0cc8553SRatan Gupta 7660fbdbce2SEmily Shaffer dataLength = std::min(static_cast<size_t>(req->bytes_to_read), 7670fbdbce2SEmily Shaffer sizeof(record) - req->offset); 768e0cc8553SRatan Gupta 769b51bf9c8SPatrick Venture std::memcpy(resp->record_data, 7701cd85963SJason M. Bills reinterpret_cast<uint8_t*>(&record) + req->offset, dataLength); 771e0cc8553SRatan Gupta 772e0cc8553SRatan Gupta *data_len = dataLength; 773e0cc8553SRatan Gupta *data_len += 2; // additional 2 bytes for next record ID 774e0cc8553SRatan Gupta 775e0cc8553SRatan Gupta return IPMI_CC_OK; 776e0cc8553SRatan Gupta } 777e0cc8553SRatan Gupta 778bbef71c2SEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 779bbef71c2SEmily Shaffer ipmi_request_t request, ipmi_response_t response, 780bbef71c2SEmily Shaffer ipmi_data_len_t data_len, ipmi_context_t context) 781bbef71c2SEmily Shaffer { 782bbef71c2SEmily Shaffer ipmi_ret_t ret = IPMI_CC_OK; 783bbef71c2SEmily Shaffer get_sdr::GetSdrReq* req = (get_sdr::GetSdrReq*)request; 784bbef71c2SEmily Shaffer get_sdr::GetSdrResp* resp = (get_sdr::GetSdrResp*)response; 785bbef71c2SEmily Shaffer get_sdr::SensorDataFullRecord record = {0}; 786bbef71c2SEmily Shaffer if (req != NULL) 787bbef71c2SEmily Shaffer { 788bbef71c2SEmily Shaffer // Note: we use an iterator so we can provide the next ID at the end of 789bbef71c2SEmily Shaffer // the call. 790bbef71c2SEmily Shaffer auto sensor = sensors.begin(); 791e0cc8553SRatan Gupta auto recordID = get_sdr::request::get_record_id(req); 792bbef71c2SEmily Shaffer 793bbef71c2SEmily Shaffer // At the beginning of a scan, the host side will send us id=0. 794e0cc8553SRatan Gupta if (recordID != 0) 795bbef71c2SEmily Shaffer { 796e0cc8553SRatan Gupta // recordID greater then 255,it means it is a FRU record. 797e0cc8553SRatan Gupta // Currently we are supporting two record types either FULL record 798e0cc8553SRatan Gupta // or FRU record. 799e0cc8553SRatan Gupta if (recordID >= FRU_RECORD_ID_START) 800e0cc8553SRatan Gupta { 801e0cc8553SRatan Gupta return ipmi_fru_get_sdr(request, response, data_len); 802e0cc8553SRatan Gupta } 803e0cc8553SRatan Gupta else 804e0cc8553SRatan Gupta { 805e0cc8553SRatan Gupta sensor = sensors.find(recordID); 806e0cc8553SRatan Gupta if (sensor == sensors.end()) 807e0cc8553SRatan Gupta { 808bbef71c2SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 809bbef71c2SEmily Shaffer } 810bbef71c2SEmily Shaffer } 811e0cc8553SRatan Gupta } 812bbef71c2SEmily Shaffer 813bbef71c2SEmily Shaffer uint8_t sensor_id = sensor->first; 814bbef71c2SEmily Shaffer 815bbef71c2SEmily Shaffer /* Header */ 816bbef71c2SEmily Shaffer get_sdr::header::set_record_id(sensor_id, &(record.header)); 817bbef71c2SEmily Shaffer record.header.sdr_version = 0x51; // Based on IPMI Spec v2.0 rev 1.1 818bbef71c2SEmily Shaffer record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD; 819bbef71c2SEmily Shaffer record.header.record_length = sizeof(get_sdr::SensorDataFullRecord); 820bbef71c2SEmily Shaffer 821bbef71c2SEmily Shaffer /* Key */ 8229642391dSTom Joseph get_sdr::key::set_owner_id_bmc(&(record.key)); 823bbef71c2SEmily Shaffer record.key.sensor_number = sensor_id; 824bbef71c2SEmily Shaffer 825bbef71c2SEmily Shaffer /* Body */ 8269642391dSTom Joseph record.body.entity_id = sensor->second.entityType; 827bbef71c2SEmily Shaffer record.body.sensor_type = sensor->second.sensorType; 828bbef71c2SEmily Shaffer record.body.event_reading_type = sensor->second.sensorReadingType; 8299642391dSTom Joseph record.body.entity_instance = sensor->second.instance; 830bbef71c2SEmily Shaffer 831bbef71c2SEmily Shaffer // Set the type-specific details given the DBus interface 832bbef71c2SEmily Shaffer ret = populate_record_from_dbus(&(record.body), &(sensor->second), 833bbef71c2SEmily Shaffer data_len); 834bbef71c2SEmily Shaffer 835bbef71c2SEmily Shaffer if (++sensor == sensors.end()) 836bbef71c2SEmily Shaffer { 837e0cc8553SRatan Gupta // we have reached till end of sensor, so assign the next record id 838e0cc8553SRatan Gupta // to 256(Max Sensor ID = 255) + FRU ID(may start with 0). 8390b02be92SPatrick Venture auto next_record_id = 8400b02be92SPatrick Venture (frus.size()) ? frus.begin()->first + FRU_RECORD_ID_START 8410b02be92SPatrick Venture : END_OF_RECORD; 842e0cc8553SRatan Gupta 843e0cc8553SRatan Gupta get_sdr::response::set_next_record_id(next_record_id, resp); 844bbef71c2SEmily Shaffer } 845bbef71c2SEmily Shaffer else 846bbef71c2SEmily Shaffer { 847bbef71c2SEmily Shaffer get_sdr::response::set_next_record_id(sensor->first, resp); 848bbef71c2SEmily Shaffer } 849bbef71c2SEmily Shaffer 8506c9ee519SEmily Shaffer if (req->offset > sizeof(record)) 8516c9ee519SEmily Shaffer { 8526c9ee519SEmily Shaffer return IPMI_CC_PARM_OUT_OF_RANGE; 8536c9ee519SEmily Shaffer } 8546c9ee519SEmily Shaffer 8556c9ee519SEmily Shaffer // data_len will ultimately be the size of the record, plus 8566c9ee519SEmily Shaffer // the size of the next record ID: 8576c9ee519SEmily Shaffer *data_len = std::min(static_cast<size_t>(req->bytes_to_read), 8586c9ee519SEmily Shaffer sizeof(record) - req->offset); 8596c9ee519SEmily Shaffer 8606c9ee519SEmily Shaffer std::memcpy(resp->record_data, 8616c9ee519SEmily Shaffer reinterpret_cast<uint8_t*>(&record) + req->offset, 8626c9ee519SEmily Shaffer *data_len); 8636c9ee519SEmily Shaffer 8646c9ee519SEmily Shaffer // data_len should include the LSB and MSB: 8651cd85963SJason M. Bills *data_len += 8661cd85963SJason M. Bills sizeof(resp->next_record_id_lsb) + sizeof(resp->next_record_id_msb); 867bbef71c2SEmily Shaffer } 868bbef71c2SEmily Shaffer 869bbef71c2SEmily Shaffer return ret; 870bbef71c2SEmily Shaffer } 871bbef71c2SEmily Shaffer 87298a23840SMatthew Barth void register_netfn_sen_functions() 87398a23840SMatthew Barth { 8740573237fSTom // <Wildcard Command> 8750b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_WILDCARD, nullptr, 8760b02be92SPatrick Venture ipmi_sen_wildcard, PRIVILEGE_USER); 87798a23840SMatthew Barth 8780573237fSTom // <Get Sensor Type> 8790b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE, nullptr, 8800b02be92SPatrick Venture ipmi_sen_get_sensor_type, PRIVILEGE_USER); 88198a23840SMatthew Barth 8820573237fSTom // <Set Sensor Reading and Event Status> 8830b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_SET_SENSOR, nullptr, 8840b02be92SPatrick Venture ipmi_sen_set_sensor, PRIVILEGE_OPERATOR); 88598a23840SMatthew Barth 8860573237fSTom // <Get Sensor Reading> 8870b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING, nullptr, 8880b02be92SPatrick Venture ipmi_sen_get_sensor_reading, PRIVILEGE_USER); 889a344afc0SEmily Shaffer 8905ca50959STom Joseph // <Reserve Device SDR Repository> 8915ca50959STom Joseph ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_RESERVE_DEVICE_SDR_REPO, 8920b02be92SPatrick Venture nullptr, ipmi_sen_reserve_sdr, PRIVILEGE_USER); 89398a23840SMatthew Barth 8945ca50959STom Joseph // <Get Device SDR Info> 8950b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_DEVICE_SDR_INFO, nullptr, 8960b02be92SPatrick Venture ipmi_sen_get_sdr_info, PRIVILEGE_USER); 897bbef71c2SEmily Shaffer 8985ca50959STom Joseph // <Get Device SDR> 8990b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_DEVICE_SDR, nullptr, 9000b02be92SPatrick Venture ipmi_sen_get_sdr, PRIVILEGE_USER); 901bbef71c2SEmily Shaffer 9025c0beec1SDhruvaraj Subhashchandran // <Get Sensor Thresholds> 9035c0beec1SDhruvaraj Subhashchandran ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_THRESHOLDS, 9045c0beec1SDhruvaraj Subhashchandran nullptr, ipmi_sen_get_sensor_thresholds, 9055c0beec1SDhruvaraj Subhashchandran PRIVILEGE_USER); 9065c0beec1SDhruvaraj Subhashchandran 90798a23840SMatthew Barth return; 90898a23840SMatthew Barth } 909