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 3498a23840SMatthew Barth void register_netfn_sen_functions() __attribute__((constructor)); 3598a23840SMatthew Barth 360b02be92SPatrick Venture struct sensorTypemap_t 370b02be92SPatrick Venture { 3898a23840SMatthew Barth uint8_t number; 3998a23840SMatthew Barth uint8_t typecode; 4098a23840SMatthew Barth char dbusname[32]; 4198a23840SMatthew Barth }; 4298a23840SMatthew Barth 4398a23840SMatthew Barth sensorTypemap_t g_SensorTypeMap[] = { 4498a23840SMatthew Barth 4598a23840SMatthew Barth {0x01, 0x6F, "Temp"}, 4698a23840SMatthew Barth {0x0C, 0x6F, "DIMM"}, 4798a23840SMatthew Barth {0x0C, 0x6F, "MEMORY_BUFFER"}, 4898a23840SMatthew Barth {0x07, 0x6F, "PROC"}, 4998a23840SMatthew Barth {0x07, 0x6F, "CORE"}, 5098a23840SMatthew Barth {0x07, 0x6F, "CPU"}, 5198a23840SMatthew Barth {0x0F, 0x6F, "BootProgress"}, 520b02be92SPatrick Venture {0xe9, 0x09, "OccStatus"}, // E9 is an internal mapping to handle sensor 530b02be92SPatrick Venture // type code os 0x09 5498a23840SMatthew Barth {0xC3, 0x6F, "BootCount"}, 5598a23840SMatthew Barth {0x1F, 0x6F, "OperatingSystemStatus"}, 5698a23840SMatthew Barth {0x12, 0x6F, "SYSTEM_EVENT"}, 5798a23840SMatthew Barth {0xC7, 0x03, "SYSTEM"}, 5898a23840SMatthew Barth {0xC7, 0x03, "MAIN_PLANAR"}, 5998a23840SMatthew Barth {0xC2, 0x6F, "PowerCap"}, 60558184eaSTom Joseph {0x0b, 0xCA, "PowerSupplyRedundancy"}, 610661beb1SJayanth Othayoth {0xDA, 0x03, "TurboAllowed"}, 62558184eaSTom Joseph {0xD8, 0xC8, "PowerSupplyDerating"}, 6398a23840SMatthew Barth {0xFF, 0x00, ""}, 6498a23840SMatthew Barth }; 6598a23840SMatthew Barth 660b02be92SPatrick Venture struct sensor_data_t 670b02be92SPatrick Venture { 6898a23840SMatthew Barth uint8_t sennum; 6998a23840SMatthew Barth } __attribute__((packed)); 7098a23840SMatthew Barth 710b02be92SPatrick Venture struct sensorreadingresp_t 720b02be92SPatrick Venture { 7398a23840SMatthew Barth uint8_t value; 7498a23840SMatthew Barth uint8_t operation; 7598a23840SMatthew Barth uint8_t indication[2]; 7698a23840SMatthew Barth } __attribute__((packed)); 7798a23840SMatthew Barth 780b02be92SPatrick Venture int get_bus_for_path(const char* path, char** busname) 790b02be92SPatrick Venture { 802ae09b9aSEmily Shaffer return mapper_get_service(bus, path, busname); 812ae09b9aSEmily Shaffer } 82d700e76aSTom 832ae09b9aSEmily Shaffer // Use a lookup table to find the interface name of a specific sensor 842ae09b9aSEmily Shaffer // This will be used until an alternative is found. this is the first 852ae09b9aSEmily Shaffer // step for mapping IPMI 860b02be92SPatrick Venture int find_openbmc_path(uint8_t num, dbus_interface_t* interface) 870b02be92SPatrick Venture { 882ae09b9aSEmily Shaffer int rc; 892ae09b9aSEmily Shaffer 902ae09b9aSEmily Shaffer const auto& sensor_it = sensors.find(num); 912ae09b9aSEmily Shaffer if (sensor_it == sensors.end()) 922ae09b9aSEmily Shaffer { 93ba23ff71SAdriana Kobylak // The sensor map does not contain the sensor requested 94ba23ff71SAdriana Kobylak return -EINVAL; 952ae09b9aSEmily Shaffer } 962ae09b9aSEmily Shaffer 972ae09b9aSEmily Shaffer const auto& info = sensor_it->second; 982ae09b9aSEmily Shaffer 998451edf5SPatrick Williams char* busname = nullptr; 1002ae09b9aSEmily Shaffer rc = get_bus_for_path(info.sensorPath.c_str(), &busname); 1010b02be92SPatrick Venture if (rc < 0) 1020b02be92SPatrick Venture { 103b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to get %s busname: %s\n", 1040b02be92SPatrick Venture info.sensorPath.c_str(), busname); 1052ae09b9aSEmily Shaffer goto final; 1062ae09b9aSEmily Shaffer } 1072ae09b9aSEmily Shaffer 1082ae09b9aSEmily Shaffer interface->sensortype = info.sensorType; 1092ae09b9aSEmily Shaffer strcpy(interface->bus, busname); 1102ae09b9aSEmily Shaffer strcpy(interface->path, info.sensorPath.c_str()); 1112ae09b9aSEmily Shaffer // Take the interface name from the beginning of the DbusInterfaceMap. This 1122ae09b9aSEmily Shaffer // works for the Value interface but may not suffice for more complex 1132ae09b9aSEmily Shaffer // sensors. 1142ae09b9aSEmily Shaffer // tracked https://github.com/openbmc/phosphor-host-ipmid/issues/103 1150b02be92SPatrick Venture strcpy(interface->interface, 1160b02be92SPatrick Venture info.propertyInterfaces.begin()->first.c_str()); 1172ae09b9aSEmily Shaffer interface->sensornumber = num; 1182ae09b9aSEmily Shaffer 1192ae09b9aSEmily Shaffer final: 1202ae09b9aSEmily Shaffer free(busname); 1212ae09b9aSEmily Shaffer return rc; 1222ae09b9aSEmily Shaffer } 1232ae09b9aSEmily Shaffer 124d700e76aSTom ///////////////////////////////////////////////////////////////////// 125d700e76aSTom // 126d700e76aSTom // Routines used by ipmi commands wanting to interact on the dbus 127d700e76aSTom // 128d700e76aSTom ///////////////////////////////////////////////////////////////////// 1290b02be92SPatrick Venture int set_sensor_dbus_state_s(uint8_t number, const char* method, 1300b02be92SPatrick Venture const char* value) 1310b02be92SPatrick Venture { 132d700e76aSTom 133d700e76aSTom dbus_interface_t a; 134d700e76aSTom int r; 135d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 136d700e76aSTom sd_bus_message* m = NULL; 137d700e76aSTom 138b51bf9c8SPatrick Venture std::fprintf(ipmidbus, 1390b02be92SPatrick Venture "Attempting to set a dbus Variant Sensor 0x%02x via %s with a " 1400b02be92SPatrick Venture "value of %s\n", 141d700e76aSTom number, method, value); 142d700e76aSTom 1432ae09b9aSEmily Shaffer r = find_openbmc_path(number, &a); 144d700e76aSTom 1450b02be92SPatrick Venture if (r < 0) 1460b02be92SPatrick Venture { 147b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); 148d700e76aSTom return 0; 149d700e76aSTom } 150d700e76aSTom 1510b02be92SPatrick Venture r = sd_bus_message_new_method_call(bus, &m, a.bus, a.path, a.interface, 1520b02be92SPatrick Venture method); 1530b02be92SPatrick Venture if (r < 0) 1540b02be92SPatrick Venture { 155b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a method call: %s", 156b51bf9c8SPatrick Venture strerror(-r)); 157d700e76aSTom goto final; 158d700e76aSTom } 159d700e76aSTom 160d700e76aSTom r = sd_bus_message_append(m, "v", "s", value); 1610b02be92SPatrick Venture if (r < 0) 1620b02be92SPatrick Venture { 163b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a input parameter: %s", 164b51bf9c8SPatrick Venture strerror(-r)); 165d700e76aSTom goto final; 166d700e76aSTom } 167d700e76aSTom 168d700e76aSTom r = sd_bus_call(bus, m, 0, &error, NULL); 1690b02be92SPatrick Venture if (r < 0) 1700b02be92SPatrick Venture { 171b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to call the method: %s", strerror(-r)); 172d700e76aSTom } 173d700e76aSTom 174d700e76aSTom final: 175d700e76aSTom sd_bus_error_free(&error); 176d700e76aSTom m = sd_bus_message_unref(m); 177d700e76aSTom 178d700e76aSTom return 0; 179d700e76aSTom } 1800b02be92SPatrick Venture int set_sensor_dbus_state_y(uint8_t number, const char* method, 1810b02be92SPatrick Venture const uint8_t value) 1820b02be92SPatrick Venture { 183d700e76aSTom 184d700e76aSTom dbus_interface_t a; 185d700e76aSTom int r; 186d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 187d700e76aSTom sd_bus_message* m = NULL; 188d700e76aSTom 189b51bf9c8SPatrick Venture std::fprintf(ipmidbus, 1900b02be92SPatrick Venture "Attempting to set a dbus Variant Sensor 0x%02x via %s with a " 1910b02be92SPatrick Venture "value of 0x%02x\n", 192d700e76aSTom number, method, value); 193d700e76aSTom 1942ae09b9aSEmily Shaffer r = find_openbmc_path(number, &a); 195d700e76aSTom 1960b02be92SPatrick Venture if (r < 0) 1970b02be92SPatrick Venture { 198b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); 199d700e76aSTom return 0; 200d700e76aSTom } 201d700e76aSTom 2020b02be92SPatrick Venture r = sd_bus_message_new_method_call(bus, &m, a.bus, a.path, a.interface, 2030b02be92SPatrick Venture method); 2040b02be92SPatrick Venture if (r < 0) 2050b02be92SPatrick Venture { 206b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a method call: %s", 207b51bf9c8SPatrick Venture strerror(-r)); 208d700e76aSTom goto final; 209d700e76aSTom } 210d700e76aSTom 211d700e76aSTom r = sd_bus_message_append(m, "v", "i", value); 2120b02be92SPatrick Venture if (r < 0) 2130b02be92SPatrick Venture { 214b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a input parameter: %s", 215b51bf9c8SPatrick Venture strerror(-r)); 216d700e76aSTom goto final; 217d700e76aSTom } 218d700e76aSTom 219d700e76aSTom r = sd_bus_call(bus, m, 0, &error, NULL); 2200b02be92SPatrick Venture if (r < 0) 2210b02be92SPatrick Venture { 222b51bf9c8SPatrick Venture std::fprintf(stderr, "12 Failed to call the method: %s", strerror(-r)); 223d700e76aSTom } 224d700e76aSTom 225d700e76aSTom final: 226d700e76aSTom sd_bus_error_free(&error); 227d700e76aSTom m = sd_bus_message_unref(m); 228d700e76aSTom 229d700e76aSTom return 0; 230d700e76aSTom } 231d700e76aSTom 2320b02be92SPatrick Venture uint8_t dbus_to_sensor_type(char* p) 2330b02be92SPatrick Venture { 23498a23840SMatthew Barth 23598a23840SMatthew Barth sensorTypemap_t* s = g_SensorTypeMap; 23698a23840SMatthew Barth char r = 0; 2370b02be92SPatrick Venture while (s->number != 0xFF) 2380b02be92SPatrick Venture { 2390b02be92SPatrick Venture if (!strcmp(s->dbusname, p)) 2400b02be92SPatrick Venture { 241558184eaSTom Joseph r = s->typecode; 24298a23840SMatthew Barth break; 24398a23840SMatthew Barth } 24498a23840SMatthew Barth s++; 24598a23840SMatthew Barth } 24698a23840SMatthew Barth 24798a23840SMatthew Barth if (s->number == 0xFF) 24898a23840SMatthew Barth printf("Failed to find Sensor Type %s\n", p); 24998a23840SMatthew Barth 25098a23840SMatthew Barth return r; 25198a23840SMatthew Barth } 25298a23840SMatthew Barth 2530b02be92SPatrick Venture uint8_t get_type_from_interface(dbus_interface_t dbus_if) 2540b02be92SPatrick Venture { 25598a23840SMatthew Barth 25698a23840SMatthew Barth char* p; 25756003453SBrad Bishop uint8_t type; 25898a23840SMatthew Barth 25998a23840SMatthew Barth // This is where sensors that do not exist in dbus but do 26098a23840SMatthew Barth // exist in the host code stop. This should indicate it 26198a23840SMatthew Barth // is not a supported sensor 2620b02be92SPatrick Venture if (dbus_if.interface[0] == 0) 2630b02be92SPatrick Venture { 2640b02be92SPatrick Venture return 0; 2650b02be92SPatrick Venture } 26698a23840SMatthew Barth 2677117441cSEmily Shaffer // Fetch type from interface itself. 2687117441cSEmily Shaffer if (dbus_if.sensortype != 0) 2697117441cSEmily Shaffer { 2707117441cSEmily Shaffer type = dbus_if.sensortype; 2710b02be92SPatrick Venture } 2720b02be92SPatrick Venture else 2730b02be92SPatrick Venture { 27498a23840SMatthew Barth // Non InventoryItems 275391f3303SEmily Shaffer p = strrchr(dbus_if.path, '/'); 27656003453SBrad Bishop type = dbus_to_sensor_type(p + 1); 27798a23840SMatthew Barth } 27898a23840SMatthew Barth 27956003453SBrad Bishop return type; 28098a23840SMatthew Barth } 28198a23840SMatthew Barth 282391f3303SEmily Shaffer // Replaces find_sensor 2830b02be92SPatrick Venture uint8_t find_type_for_sensor_number(uint8_t num) 2840b02be92SPatrick Venture { 285391f3303SEmily Shaffer int r; 286391f3303SEmily Shaffer dbus_interface_t dbus_if; 2872ae09b9aSEmily Shaffer r = find_openbmc_path(num, &dbus_if); 2880b02be92SPatrick Venture if (r < 0) 2890b02be92SPatrick Venture { 290b51bf9c8SPatrick Venture std::fprintf(stderr, "Could not find sensor %d\n", num); 29191875f77SLei YU return 0; 292391f3303SEmily Shaffer } 293391f3303SEmily Shaffer return get_type_from_interface(dbus_if); 294391f3303SEmily Shaffer } 295391f3303SEmily Shaffer 29698a23840SMatthew Barth ipmi_ret_t ipmi_sen_get_sensor_type(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 2970b02be92SPatrick Venture ipmi_request_t request, 2980b02be92SPatrick Venture ipmi_response_t response, 2990b02be92SPatrick Venture ipmi_data_len_t data_len, 3000b02be92SPatrick Venture ipmi_context_t context) 30198a23840SMatthew Barth { 30298a23840SMatthew Barth sensor_data_t* reqptr = (sensor_data_t*)request; 30398a23840SMatthew Barth ipmi_ret_t rc = IPMI_CC_OK; 30498a23840SMatthew Barth 30598a23840SMatthew Barth printf("IPMI GET_SENSOR_TYPE [0x%02X]\n", reqptr->sennum); 30698a23840SMatthew Barth 30798a23840SMatthew Barth // TODO Not sure what the System-event-sensor is suppose to return 30898a23840SMatthew Barth // need to ask Hostboot team 30998a23840SMatthew Barth unsigned char buf[] = {0x00, 0x6F}; 31098a23840SMatthew Barth 311391f3303SEmily Shaffer buf[0] = find_type_for_sensor_number(reqptr->sennum); 31298a23840SMatthew Barth 31398a23840SMatthew Barth // HACK UNTIL Dbus gets updated or we find a better way 3140b02be92SPatrick Venture if (buf[0] == 0) 3150b02be92SPatrick Venture { 31698a23840SMatthew Barth rc = IPMI_CC_SENSOR_INVALID; 31798a23840SMatthew Barth } 31898a23840SMatthew Barth 31998a23840SMatthew Barth *data_len = sizeof(buf); 320b51bf9c8SPatrick Venture std::memcpy(response, &buf, *data_len); 32198a23840SMatthew Barth 32298a23840SMatthew Barth return rc; 32398a23840SMatthew Barth } 32498a23840SMatthew Barth 3250b02be92SPatrick Venture const std::set<std::string> analogSensorInterfaces = { 326cc941e15SEmily Shaffer "xyz.openbmc_project.Sensor.Value", 327e9a64056SPatrick Venture "xyz.openbmc_project.Control.FanPwm", 328cc941e15SEmily Shaffer }; 329cc941e15SEmily Shaffer 330cc941e15SEmily Shaffer bool isAnalogSensor(const std::string& interface) 331cc941e15SEmily Shaffer { 332cc941e15SEmily Shaffer return (analogSensorInterfaces.count(interface)); 333cc941e15SEmily Shaffer } 334cc941e15SEmily Shaffer 335be703f71STom Joseph ipmi_ret_t setSensorReading(void* request) 336be703f71STom Joseph { 337816e92b5STom Joseph ipmi::sensor::SetSensorReadingReq cmdData = 338816e92b5STom Joseph *(static_cast<ipmi::sensor::SetSensorReadingReq*>(request)); 339be703f71STom Joseph 340be703f71STom Joseph // Check if the Sensor Number is present 341e0af7209SDhruvaraj Subhashchandran const auto iter = sensors.find(cmdData.number); 342be703f71STom Joseph if (iter == sensors.end()) 343be703f71STom Joseph { 344be703f71STom Joseph return IPMI_CC_SENSOR_INVALID; 345be703f71STom Joseph } 346be703f71STom Joseph 34718e99992SDhruvaraj Subhashchandran try 34818e99992SDhruvaraj Subhashchandran { 3490922bde4SJayanth Othayoth if (ipmi::sensor::Mutability::Write != 3500922bde4SJayanth Othayoth (iter->second.mutability & ipmi::sensor::Mutability::Write)) 3510922bde4SJayanth Othayoth { 3520922bde4SJayanth Othayoth log<level::ERR>("Sensor Set operation is not allowed", 3530922bde4SJayanth Othayoth entry("SENSOR_NUM=%d", cmdData.number)); 3540922bde4SJayanth Othayoth return IPMI_CC_ILLEGAL_COMMAND; 3550922bde4SJayanth Othayoth } 356e0af7209SDhruvaraj Subhashchandran return iter->second.updateFunc(cmdData, iter->second); 357be703f71STom Joseph } 35818e99992SDhruvaraj Subhashchandran catch (InternalFailure& e) 35918e99992SDhruvaraj Subhashchandran { 36018e99992SDhruvaraj Subhashchandran log<level::ERR>("Set sensor failed", 36118e99992SDhruvaraj Subhashchandran entry("SENSOR_NUM=%d", cmdData.number)); 36218e99992SDhruvaraj Subhashchandran commit<InternalFailure>(); 36318e99992SDhruvaraj Subhashchandran } 3648202432fSTom Joseph catch (const std::runtime_error& e) 3658202432fSTom Joseph { 3668202432fSTom Joseph log<level::ERR>(e.what()); 3678202432fSTom Joseph } 36818e99992SDhruvaraj Subhashchandran 36918e99992SDhruvaraj Subhashchandran return IPMI_CC_UNSPECIFIED_ERROR; 37018e99992SDhruvaraj Subhashchandran } 37198a23840SMatthew Barth 37298a23840SMatthew Barth ipmi_ret_t ipmi_sen_set_sensor(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 37398a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 37498a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 37598a23840SMatthew Barth { 37698a23840SMatthew Barth sensor_data_t* reqptr = (sensor_data_t*)request; 37798a23840SMatthew Barth 3785fb14603SAditya Saripalli log<level::DEBUG>("IPMI SET_SENSOR", 3795fb14603SAditya Saripalli entry("SENSOR_NUM=0x%02x", reqptr->sennum)); 38098a23840SMatthew Barth 381be703f71STom Joseph /* 382be703f71STom Joseph * This would support the Set Sensor Reading command for the presence 383be703f71STom Joseph * and functional state of Processor, Core & DIMM. For the remaining 384be703f71STom Joseph * sensors the existing support is invoked. 385be703f71STom Joseph */ 386be703f71STom Joseph auto ipmiRC = setSensorReading(request); 387be703f71STom Joseph 388be703f71STom Joseph if (ipmiRC == IPMI_CC_SENSOR_INVALID) 389be703f71STom Joseph { 39098a23840SMatthew Barth updateSensorRecordFromSSRAESC(reqptr); 391be703f71STom Joseph ipmiRC = IPMI_CC_OK; 392be703f71STom Joseph } 39398a23840SMatthew Barth 39498a23840SMatthew Barth *data_len = 0; 395be703f71STom Joseph return ipmiRC; 39698a23840SMatthew Barth } 39798a23840SMatthew Barth 3983ee668f9STom Joseph ipmi_ret_t ipmi_sen_get_sensor_reading(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 3990b02be92SPatrick Venture ipmi_request_t request, 4000b02be92SPatrick Venture ipmi_response_t response, 4010b02be92SPatrick Venture ipmi_data_len_t data_len, 4020b02be92SPatrick Venture ipmi_context_t context) 4033ee668f9STom Joseph { 4043ee668f9STom Joseph sensor_data_t* reqptr = (sensor_data_t*)request; 4053ee668f9STom Joseph sensorreadingresp_t* resp = (sensorreadingresp_t*)response; 4063ee668f9STom Joseph ipmi::sensor::GetSensorResponse getResponse{}; 4073ee668f9STom Joseph static constexpr auto scanningEnabledBit = 6; 4083ee668f9STom Joseph 40914c15467STom Joseph const auto iter = sensors.find(reqptr->sennum); 41014c15467STom Joseph if (iter == sensors.end()) 41114c15467STom Joseph { 412ba23ff71SAdriana Kobylak return IPMI_CC_SENSOR_INVALID; 41314c15467STom Joseph } 41413b87a3eSTom Joseph if (ipmi::sensor::Mutability::Read != 41513b87a3eSTom Joseph (iter->second.mutability & ipmi::sensor::Mutability::Read)) 41613b87a3eSTom Joseph { 4176ccf8818SJayanth Othayoth return IPMI_CC_ILLEGAL_COMMAND; 41813b87a3eSTom Joseph } 41914c15467STom Joseph 42014c15467STom Joseph try 42114c15467STom Joseph { 422c6162fb6STom Joseph getResponse = iter->second.getFunc(iter->second); 42314c15467STom Joseph *data_len = getResponse.size(); 424b51bf9c8SPatrick Venture std::memcpy(resp, getResponse.data(), *data_len); 425c6162fb6STom Joseph resp->operation = 1 << scanningEnabledBit; 42614c15467STom Joseph return IPMI_CC_OK; 42714c15467STom Joseph } 4283ee668f9STom Joseph catch (const std::exception& e) 42914c15467STom Joseph { 430c6162fb6STom Joseph *data_len = getResponse.size(); 431b51bf9c8SPatrick Venture std::memcpy(resp, getResponse.data(), *data_len); 432c6162fb6STom Joseph return IPMI_CC_OK; 43314c15467STom Joseph } 43498a23840SMatthew Barth } 43598a23840SMatthew Barth 4360ac0dd23STom Joseph void getSensorThresholds(uint8_t sensorNum, 4370ac0dd23STom Joseph get_sdr::GetSensorThresholdsResponse* response) 4380ac0dd23STom Joseph { 4390ac0dd23STom Joseph constexpr auto warningThreshIntf = 4400ac0dd23STom Joseph "xyz.openbmc_project.Sensor.Threshold.Warning"; 4410ac0dd23STom Joseph constexpr auto criticalThreshIntf = 4420ac0dd23STom Joseph "xyz.openbmc_project.Sensor.Threshold.Critical"; 4430ac0dd23STom Joseph 4440ac0dd23STom Joseph sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; 4450ac0dd23STom Joseph 4460ac0dd23STom Joseph const auto iter = sensors.find(sensorNum); 4470ac0dd23STom Joseph const auto info = iter->second; 4480ac0dd23STom Joseph 4490ac0dd23STom Joseph auto service = ipmi::getService(bus, info.sensorInterface, info.sensorPath); 4500ac0dd23STom Joseph 4510b02be92SPatrick Venture auto warnThresholds = ipmi::getAllDbusProperties( 4520b02be92SPatrick Venture bus, service, info.sensorPath, warningThreshIntf); 4530ac0dd23STom Joseph 4541e12112bSJames Feist double warnLow = mapbox::util::apply_visitor(ipmi::VariantToDoubleVisitor(), 4551e12112bSJames Feist warnThresholds["WarningLow"]); 4561e12112bSJames Feist double warnHigh = mapbox::util::apply_visitor( 4571e12112bSJames Feist ipmi::VariantToDoubleVisitor(), warnThresholds["WarningHigh"]); 4580ac0dd23STom Joseph 4590ac0dd23STom Joseph if (warnLow != 0) 4600ac0dd23STom Joseph { 461586d35b4SPatrick Venture warnLow *= std::pow(10, info.scale - info.exponentR); 4620b02be92SPatrick Venture response->lowerNonCritical = static_cast<uint8_t>( 4630b02be92SPatrick Venture (warnLow - info.scaledOffset) / info.coefficientM); 4640ac0dd23STom Joseph response->validMask |= static_cast<uint8_t>( 4650ac0dd23STom Joseph ipmi::sensor::ThresholdMask::NON_CRITICAL_LOW_MASK); 4660ac0dd23STom Joseph } 4670ac0dd23STom Joseph 4680ac0dd23STom Joseph if (warnHigh != 0) 4690ac0dd23STom Joseph { 470586d35b4SPatrick Venture warnHigh *= std::pow(10, info.scale - info.exponentR); 4710b02be92SPatrick Venture response->upperNonCritical = static_cast<uint8_t>( 4720b02be92SPatrick Venture (warnHigh - info.scaledOffset) / info.coefficientM); 4730ac0dd23STom Joseph response->validMask |= static_cast<uint8_t>( 4740ac0dd23STom Joseph ipmi::sensor::ThresholdMask::NON_CRITICAL_HIGH_MASK); 4750ac0dd23STom Joseph } 4760ac0dd23STom Joseph 4770b02be92SPatrick Venture auto critThresholds = ipmi::getAllDbusProperties( 4780b02be92SPatrick Venture bus, service, info.sensorPath, criticalThreshIntf); 4791e12112bSJames Feist double critLow = mapbox::util::apply_visitor(ipmi::VariantToDoubleVisitor(), 4801e12112bSJames Feist critThresholds["CriticalLow"]); 4811e12112bSJames Feist double critHigh = mapbox::util::apply_visitor( 4821e12112bSJames Feist ipmi::VariantToDoubleVisitor(), critThresholds["CriticalHigh"]); 4830ac0dd23STom Joseph 4840ac0dd23STom Joseph if (critLow != 0) 4850ac0dd23STom Joseph { 486586d35b4SPatrick Venture critLow *= std::pow(10, info.scale - info.exponentR); 4870b02be92SPatrick Venture response->lowerCritical = static_cast<uint8_t>( 4880b02be92SPatrick Venture (critLow - info.scaledOffset) / info.coefficientM); 4890ac0dd23STom Joseph response->validMask |= static_cast<uint8_t>( 4900ac0dd23STom Joseph ipmi::sensor::ThresholdMask::CRITICAL_LOW_MASK); 4910ac0dd23STom Joseph } 4920ac0dd23STom Joseph 4930ac0dd23STom Joseph if (critHigh != 0) 4940ac0dd23STom Joseph { 495586d35b4SPatrick Venture critHigh *= std::pow(10, info.scale - info.exponentR); 4960b02be92SPatrick Venture response->upperCritical = static_cast<uint8_t>( 4970b02be92SPatrick Venture (critHigh - info.scaledOffset) / info.coefficientM); 4980ac0dd23STom Joseph response->validMask |= static_cast<uint8_t>( 4990ac0dd23STom Joseph ipmi::sensor::ThresholdMask::CRITICAL_HIGH_MASK); 5000ac0dd23STom Joseph } 5010ac0dd23STom Joseph } 5020ac0dd23STom Joseph 5035c0beec1SDhruvaraj Subhashchandran ipmi_ret_t ipmi_sen_get_sensor_thresholds(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 5040b02be92SPatrick Venture ipmi_request_t request, 5050b02be92SPatrick Venture ipmi_response_t response, 5060b02be92SPatrick Venture ipmi_data_len_t data_len, 5070b02be92SPatrick Venture ipmi_context_t context) 5085c0beec1SDhruvaraj Subhashchandran { 5090ac0dd23STom Joseph constexpr auto valueInterface = "xyz.openbmc_project.Sensor.Value"; 5105c0beec1SDhruvaraj Subhashchandran 5115c0beec1SDhruvaraj Subhashchandran if (*data_len != sizeof(uint8_t)) 5125c0beec1SDhruvaraj Subhashchandran { 5130ac0dd23STom Joseph *data_len = 0; 5145c0beec1SDhruvaraj Subhashchandran return IPMI_CC_REQ_DATA_LEN_INVALID; 5155c0beec1SDhruvaraj Subhashchandran } 5165c0beec1SDhruvaraj Subhashchandran 5170ac0dd23STom Joseph auto sensorNum = *(reinterpret_cast<const uint8_t*>(request)); 5180ac0dd23STom Joseph *data_len = 0; 5195c0beec1SDhruvaraj Subhashchandran 5205c0beec1SDhruvaraj Subhashchandran const auto iter = sensors.find(sensorNum); 5215c0beec1SDhruvaraj Subhashchandran if (iter == sensors.end()) 5225c0beec1SDhruvaraj Subhashchandran { 5235c0beec1SDhruvaraj Subhashchandran return IPMI_CC_SENSOR_INVALID; 5245c0beec1SDhruvaraj Subhashchandran } 5255c0beec1SDhruvaraj Subhashchandran 5260ac0dd23STom Joseph const auto info = iter->second; 5275c0beec1SDhruvaraj Subhashchandran 5285c0beec1SDhruvaraj Subhashchandran // Proceed only if the sensor value interface is implemented. 5290ac0dd23STom Joseph if (info.propertyInterfaces.find(valueInterface) == 5300ac0dd23STom Joseph info.propertyInterfaces.end()) 5315c0beec1SDhruvaraj Subhashchandran { 5325c0beec1SDhruvaraj Subhashchandran // return with valid mask as 0 5335c0beec1SDhruvaraj Subhashchandran return IPMI_CC_OK; 5345c0beec1SDhruvaraj Subhashchandran } 5355c0beec1SDhruvaraj Subhashchandran 5360ac0dd23STom Joseph auto responseData = 5370ac0dd23STom Joseph reinterpret_cast<get_sdr::GetSensorThresholdsResponse*>(response); 5385c0beec1SDhruvaraj Subhashchandran 5395c0beec1SDhruvaraj Subhashchandran try 5405c0beec1SDhruvaraj Subhashchandran { 5410ac0dd23STom Joseph getSensorThresholds(sensorNum, responseData); 5425c0beec1SDhruvaraj Subhashchandran } 5430ac0dd23STom Joseph catch (std::exception& e) 5445c0beec1SDhruvaraj Subhashchandran { 5450ac0dd23STom Joseph // Mask if the property is not present 5465c0beec1SDhruvaraj Subhashchandran responseData->validMask = 0; 5475c0beec1SDhruvaraj Subhashchandran } 5485c0beec1SDhruvaraj Subhashchandran 5495c0beec1SDhruvaraj Subhashchandran *data_len = sizeof(get_sdr::GetSensorThresholdsResponse); 5505c0beec1SDhruvaraj Subhashchandran return IPMI_CC_OK; 5515c0beec1SDhruvaraj Subhashchandran } 5525c0beec1SDhruvaraj Subhashchandran 55398a23840SMatthew Barth ipmi_ret_t ipmi_sen_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 55498a23840SMatthew Barth ipmi_request_t request, ipmi_response_t response, 55598a23840SMatthew Barth ipmi_data_len_t data_len, ipmi_context_t context) 55698a23840SMatthew Barth { 55770aa8d96SNan Li ipmi_ret_t rc = IPMI_CC_INVALID; 55898a23840SMatthew Barth 55998a23840SMatthew Barth printf("IPMI S/E Wildcard Netfn:[0x%X], Cmd:[0x%X]\n", netfn, cmd); 56098a23840SMatthew Barth *data_len = 0; 56198a23840SMatthew Barth 56298a23840SMatthew Barth return rc; 56398a23840SMatthew Barth } 56498a23840SMatthew Barth 565d06e0e7eSEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 566d06e0e7eSEmily Shaffer ipmi_request_t request, 567d06e0e7eSEmily Shaffer ipmi_response_t response, 568d06e0e7eSEmily Shaffer ipmi_data_len_t data_len, 569d06e0e7eSEmily Shaffer ipmi_context_t context) 570d06e0e7eSEmily Shaffer { 571d06e0e7eSEmily Shaffer auto resp = static_cast<get_sdr_info::GetSdrInfoResp*>(response); 572d06e0e7eSEmily Shaffer if (request == nullptr || 573d06e0e7eSEmily Shaffer get_sdr_info::request::get_count(request) == false) 574d06e0e7eSEmily Shaffer { 575d06e0e7eSEmily Shaffer // Get Sensor Count 576e0cc8553SRatan Gupta resp->count = sensors.size() + frus.size(); 577d06e0e7eSEmily Shaffer } 578d06e0e7eSEmily Shaffer else 579d06e0e7eSEmily Shaffer { 580d06e0e7eSEmily Shaffer resp->count = 1; 581d06e0e7eSEmily Shaffer } 582d06e0e7eSEmily Shaffer 583d06e0e7eSEmily Shaffer // Multiple LUNs not supported. 584d06e0e7eSEmily Shaffer namespace response = get_sdr_info::response; 585d06e0e7eSEmily Shaffer response::set_lun_present(0, &(resp->luns_and_dynamic_population)); 586d06e0e7eSEmily Shaffer response::set_lun_not_present(1, &(resp->luns_and_dynamic_population)); 587d06e0e7eSEmily Shaffer response::set_lun_not_present(2, &(resp->luns_and_dynamic_population)); 588d06e0e7eSEmily Shaffer response::set_lun_not_present(3, &(resp->luns_and_dynamic_population)); 589d06e0e7eSEmily Shaffer response::set_static_population(&(resp->luns_and_dynamic_population)); 590d06e0e7eSEmily Shaffer 591d06e0e7eSEmily Shaffer *data_len = SDR_INFO_RESP_SIZE; 592d06e0e7eSEmily Shaffer 593d06e0e7eSEmily Shaffer return IPMI_CC_OK; 594d06e0e7eSEmily Shaffer } 595d06e0e7eSEmily Shaffer 596a344afc0SEmily Shaffer ipmi_ret_t ipmi_sen_reserve_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 597a344afc0SEmily Shaffer ipmi_request_t request, 598a344afc0SEmily Shaffer ipmi_response_t response, 599a344afc0SEmily Shaffer ipmi_data_len_t data_len, 600a344afc0SEmily Shaffer ipmi_context_t context) 601a344afc0SEmily Shaffer { 602a344afc0SEmily Shaffer // A constant reservation ID is okay until we implement add/remove SDR. 603a344afc0SEmily Shaffer const uint16_t reservation_id = 1; 604a344afc0SEmily Shaffer *(uint16_t*)response = reservation_id; 6055a5a6282SEmily Shaffer *data_len = sizeof(uint16_t); 606a344afc0SEmily Shaffer 607a344afc0SEmily Shaffer printf("Created new IPMI SDR reservation ID %d\n", *(uint16_t*)response); 608a344afc0SEmily Shaffer return IPMI_CC_OK; 609a344afc0SEmily Shaffer } 61098a23840SMatthew Barth 611dc212b23STom Joseph void setUnitFieldsForObject(const ipmi::sensor::Info* info, 612cc941e15SEmily Shaffer get_sdr::SensorDataFullRecordBody* body) 613bbef71c2SEmily Shaffer { 614bbef71c2SEmily Shaffer namespace server = sdbusplus::xyz::openbmc_project::Sensor::server; 615dc212b23STom Joseph try 616dc212b23STom Joseph { 617dc212b23STom Joseph auto unit = server::Value::convertUnitFromString(info->unit); 618bbef71c2SEmily Shaffer // Unit strings defined in 619bbef71c2SEmily Shaffer // phosphor-dbus-interfaces/xyz/openbmc_project/Sensor/Value.interface.yaml 620bbef71c2SEmily Shaffer switch (unit) 621bbef71c2SEmily Shaffer { 622bbef71c2SEmily Shaffer case server::Value::Unit::DegreesC: 623bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_DEGREES_C; 624bbef71c2SEmily Shaffer break; 625bbef71c2SEmily Shaffer case server::Value::Unit::RPMS: 6260b02be92SPatrick Venture body->sensor_units_2_base = 6270b02be92SPatrick Venture get_sdr::SENSOR_UNIT_REVOLUTIONS; // revolutions 628bbef71c2SEmily Shaffer get_sdr::body::set_rate_unit(0b100, body); // per minute 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 } 651cc941e15SEmily Shaffer catch (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 760*0fbdbce2SEmily Shaffer // Check for invalid offset size 761*0fbdbce2SEmily Shaffer if (req->offset > sizeof(record)) 762e0cc8553SRatan Gupta { 763*0fbdbce2SEmily Shaffer return IPMI_CC_PARM_OUT_OF_RANGE; 764e0cc8553SRatan Gupta } 765e0cc8553SRatan Gupta 766*0fbdbce2SEmily Shaffer dataLength = std::min(static_cast<size_t>(req->bytes_to_read), 767*0fbdbce2SEmily Shaffer sizeof(record) - req->offset); 768e0cc8553SRatan Gupta 769b51bf9c8SPatrick Venture std::memcpy(resp->record_data, 770b51bf9c8SPatrick Venture reinterpret_cast<uint8_t*>(&record) + req->offset, 771*0fbdbce2SEmily Shaffer dataLength); 772e0cc8553SRatan Gupta 773e0cc8553SRatan Gupta *data_len = dataLength; 774e0cc8553SRatan Gupta *data_len += 2; // additional 2 bytes for next record ID 775e0cc8553SRatan Gupta 776e0cc8553SRatan Gupta return IPMI_CC_OK; 777e0cc8553SRatan Gupta } 778e0cc8553SRatan Gupta 779bbef71c2SEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 780bbef71c2SEmily Shaffer ipmi_request_t request, ipmi_response_t response, 781bbef71c2SEmily Shaffer ipmi_data_len_t data_len, ipmi_context_t context) 782bbef71c2SEmily Shaffer { 783bbef71c2SEmily Shaffer ipmi_ret_t ret = IPMI_CC_OK; 784bbef71c2SEmily Shaffer get_sdr::GetSdrReq* req = (get_sdr::GetSdrReq*)request; 785bbef71c2SEmily Shaffer get_sdr::GetSdrResp* resp = (get_sdr::GetSdrResp*)response; 786bbef71c2SEmily Shaffer get_sdr::SensorDataFullRecord record = {0}; 787bbef71c2SEmily Shaffer if (req != NULL) 788bbef71c2SEmily Shaffer { 789bbef71c2SEmily Shaffer // Note: we use an iterator so we can provide the next ID at the end of 790bbef71c2SEmily Shaffer // the call. 791bbef71c2SEmily Shaffer auto sensor = sensors.begin(); 792e0cc8553SRatan Gupta auto recordID = get_sdr::request::get_record_id(req); 793bbef71c2SEmily Shaffer 794bbef71c2SEmily Shaffer // At the beginning of a scan, the host side will send us id=0. 795e0cc8553SRatan Gupta if (recordID != 0) 796bbef71c2SEmily Shaffer { 797e0cc8553SRatan Gupta // recordID greater then 255,it means it is a FRU record. 798e0cc8553SRatan Gupta // Currently we are supporting two record types either FULL record 799e0cc8553SRatan Gupta // or FRU record. 800e0cc8553SRatan Gupta if (recordID >= FRU_RECORD_ID_START) 801e0cc8553SRatan Gupta { 802e0cc8553SRatan Gupta return ipmi_fru_get_sdr(request, response, data_len); 803e0cc8553SRatan Gupta } 804e0cc8553SRatan Gupta else 805e0cc8553SRatan Gupta { 806e0cc8553SRatan Gupta sensor = sensors.find(recordID); 807e0cc8553SRatan Gupta if (sensor == sensors.end()) 808e0cc8553SRatan Gupta { 809bbef71c2SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 810bbef71c2SEmily Shaffer } 811bbef71c2SEmily Shaffer } 812e0cc8553SRatan Gupta } 813bbef71c2SEmily Shaffer 814bbef71c2SEmily Shaffer uint8_t sensor_id = sensor->first; 815bbef71c2SEmily Shaffer 816bbef71c2SEmily Shaffer /* Header */ 817bbef71c2SEmily Shaffer get_sdr::header::set_record_id(sensor_id, &(record.header)); 818bbef71c2SEmily Shaffer record.header.sdr_version = 0x51; // Based on IPMI Spec v2.0 rev 1.1 819bbef71c2SEmily Shaffer record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD; 820bbef71c2SEmily Shaffer record.header.record_length = sizeof(get_sdr::SensorDataFullRecord); 821bbef71c2SEmily Shaffer 822bbef71c2SEmily Shaffer /* Key */ 8239642391dSTom Joseph get_sdr::key::set_owner_id_bmc(&(record.key)); 824bbef71c2SEmily Shaffer record.key.sensor_number = sensor_id; 825bbef71c2SEmily Shaffer 826bbef71c2SEmily Shaffer /* Body */ 8279642391dSTom Joseph record.body.entity_id = sensor->second.entityType; 828bbef71c2SEmily Shaffer record.body.sensor_type = sensor->second.sensorType; 829bbef71c2SEmily Shaffer record.body.event_reading_type = sensor->second.sensorReadingType; 8309642391dSTom Joseph record.body.entity_instance = sensor->second.instance; 831bbef71c2SEmily Shaffer 832bbef71c2SEmily Shaffer // Set the type-specific details given the DBus interface 833bbef71c2SEmily Shaffer ret = populate_record_from_dbus(&(record.body), &(sensor->second), 834bbef71c2SEmily Shaffer data_len); 835bbef71c2SEmily Shaffer 836bbef71c2SEmily Shaffer if (++sensor == sensors.end()) 837bbef71c2SEmily Shaffer { 838e0cc8553SRatan Gupta // we have reached till end of sensor, so assign the next record id 839e0cc8553SRatan Gupta // to 256(Max Sensor ID = 255) + FRU ID(may start with 0). 8400b02be92SPatrick Venture auto next_record_id = 8410b02be92SPatrick Venture (frus.size()) ? frus.begin()->first + FRU_RECORD_ID_START 8420b02be92SPatrick Venture : END_OF_RECORD; 843e0cc8553SRatan Gupta 844e0cc8553SRatan Gupta get_sdr::response::set_next_record_id(next_record_id, resp); 845bbef71c2SEmily Shaffer } 846bbef71c2SEmily Shaffer else 847bbef71c2SEmily Shaffer { 848bbef71c2SEmily Shaffer get_sdr::response::set_next_record_id(sensor->first, resp); 849bbef71c2SEmily Shaffer } 850bbef71c2SEmily Shaffer 851bbef71c2SEmily Shaffer *data_len = sizeof(get_sdr::GetSdrResp) - req->offset; 852b51bf9c8SPatrick Venture std::memcpy(resp->record_data, (char*)&record + req->offset, 853bbef71c2SEmily Shaffer sizeof(get_sdr::SensorDataFullRecord) - req->offset); 854bbef71c2SEmily Shaffer } 855bbef71c2SEmily Shaffer 856bbef71c2SEmily Shaffer return ret; 857bbef71c2SEmily Shaffer } 858bbef71c2SEmily Shaffer 85998a23840SMatthew Barth void register_netfn_sen_functions() 86098a23840SMatthew Barth { 8610573237fSTom // <Wildcard Command> 8620b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_WILDCARD, nullptr, 8630b02be92SPatrick Venture ipmi_sen_wildcard, PRIVILEGE_USER); 86498a23840SMatthew Barth 8650573237fSTom // <Get Sensor Type> 8660b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_TYPE, nullptr, 8670b02be92SPatrick Venture ipmi_sen_get_sensor_type, PRIVILEGE_USER); 86898a23840SMatthew Barth 8690573237fSTom // <Set Sensor Reading and Event Status> 8700b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_SET_SENSOR, nullptr, 8710b02be92SPatrick Venture ipmi_sen_set_sensor, PRIVILEGE_OPERATOR); 87298a23840SMatthew Barth 8730573237fSTom // <Get Sensor Reading> 8740b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_READING, nullptr, 8750b02be92SPatrick Venture ipmi_sen_get_sensor_reading, PRIVILEGE_USER); 876a344afc0SEmily Shaffer 8775ca50959STom Joseph // <Reserve Device SDR Repository> 8785ca50959STom Joseph ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_RESERVE_DEVICE_SDR_REPO, 8790b02be92SPatrick Venture nullptr, ipmi_sen_reserve_sdr, PRIVILEGE_USER); 88098a23840SMatthew Barth 8815ca50959STom Joseph // <Get Device SDR Info> 8820b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_DEVICE_SDR_INFO, nullptr, 8830b02be92SPatrick Venture ipmi_sen_get_sdr_info, PRIVILEGE_USER); 884bbef71c2SEmily Shaffer 8855ca50959STom Joseph // <Get Device SDR> 8860b02be92SPatrick Venture ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_DEVICE_SDR, nullptr, 8870b02be92SPatrick Venture ipmi_sen_get_sdr, PRIVILEGE_USER); 888bbef71c2SEmily Shaffer 8895c0beec1SDhruvaraj Subhashchandran // <Get Sensor Thresholds> 8905c0beec1SDhruvaraj Subhashchandran ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_SENSOR_THRESHOLDS, 8915c0beec1SDhruvaraj Subhashchandran nullptr, ipmi_sen_get_sensor_thresholds, 8925c0beec1SDhruvaraj Subhashchandran PRIVILEGE_USER); 8935c0beec1SDhruvaraj Subhashchandran 89498a23840SMatthew Barth return; 89598a23840SMatthew Barth } 896