19cf85627SBrandon Kim #include "config.h" 29cf85627SBrandon Kim 346470a38SPatrick Venture #include "sensorhandler.hpp" 40b02be92SPatrick Venture 599bf1c41SPatrick Venture #include "entity_map_json.hpp" 60b02be92SPatrick Venture #include "fruread.hpp" 70b02be92SPatrick Venture 8d700e76aSTom #include <mapper.h> 998a23840SMatthew Barth #include <systemd/sd-bus.h> 100b02be92SPatrick Venture 110b02be92SPatrick Venture #include <bitset> 12586d35b4SPatrick Venture #include <cmath> 13b51bf9c8SPatrick Venture #include <cstring> 14e08fbffcSVernon Mauery #include <ipmid/api.hpp> 1533250240SVernon Mauery #include <ipmid/types.hpp> 166a98fe7fSVernon Mauery #include <ipmid/utils.hpp> 1718e99992SDhruvaraj Subhashchandran #include <phosphor-logging/elog-errors.hpp> 180b02be92SPatrick Venture #include <phosphor-logging/log.hpp> 194c008028SWilliam A. Kennington III #include <sdbusplus/message/types.hpp> 200b02be92SPatrick Venture #include <set> 210b02be92SPatrick Venture #include <xyz/openbmc_project/Common/error.hpp> 220b02be92SPatrick Venture #include <xyz/openbmc_project/Sensor/Value/server.hpp> 230b02be92SPatrick Venture 24e0cc8553SRatan Gupta static constexpr uint8_t fruInventoryDevice = 0x10; 25e0cc8553SRatan Gupta static constexpr uint8_t IPMIFruInventory = 0x02; 26e0cc8553SRatan Gupta static constexpr uint8_t BMCSlaveAddress = 0x20; 27e0cc8553SRatan Gupta 2898a23840SMatthew Barth extern int updateSensorRecordFromSSRAESC(const void*); 29d700e76aSTom extern sd_bus* bus; 30db0cbe64SPatrick Venture 31db0cbe64SPatrick Venture namespace ipmi 32db0cbe64SPatrick Venture { 33db0cbe64SPatrick Venture namespace sensor 34db0cbe64SPatrick Venture { 35db0cbe64SPatrick Venture extern const IdInfoMap sensors; 36db0cbe64SPatrick Venture } // namespace sensor 37db0cbe64SPatrick Venture } // namespace ipmi 38db0cbe64SPatrick Venture 39e0cc8553SRatan Gupta extern const FruMap frus; 40e0cc8553SRatan Gupta 41be703f71STom Joseph using namespace phosphor::logging; 4218e99992SDhruvaraj Subhashchandran using InternalFailure = 4318e99992SDhruvaraj Subhashchandran sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 4498a23840SMatthew Barth 4598a23840SMatthew Barth void register_netfn_sen_functions() __attribute__((constructor)); 4698a23840SMatthew Barth 470b02be92SPatrick Venture struct sensorTypemap_t 480b02be92SPatrick Venture { 4998a23840SMatthew Barth uint8_t number; 5098a23840SMatthew Barth uint8_t typecode; 5198a23840SMatthew Barth char dbusname[32]; 5298a23840SMatthew Barth }; 5398a23840SMatthew Barth 5498a23840SMatthew Barth sensorTypemap_t g_SensorTypeMap[] = { 5598a23840SMatthew Barth 5698a23840SMatthew Barth {0x01, 0x6F, "Temp"}, 5798a23840SMatthew Barth {0x0C, 0x6F, "DIMM"}, 5898a23840SMatthew Barth {0x0C, 0x6F, "MEMORY_BUFFER"}, 5998a23840SMatthew Barth {0x07, 0x6F, "PROC"}, 6098a23840SMatthew Barth {0x07, 0x6F, "CORE"}, 6198a23840SMatthew Barth {0x07, 0x6F, "CPU"}, 6298a23840SMatthew Barth {0x0F, 0x6F, "BootProgress"}, 630b02be92SPatrick Venture {0xe9, 0x09, "OccStatus"}, // E9 is an internal mapping to handle sensor 640b02be92SPatrick Venture // type code os 0x09 6598a23840SMatthew Barth {0xC3, 0x6F, "BootCount"}, 6698a23840SMatthew Barth {0x1F, 0x6F, "OperatingSystemStatus"}, 6798a23840SMatthew Barth {0x12, 0x6F, "SYSTEM_EVENT"}, 6898a23840SMatthew Barth {0xC7, 0x03, "SYSTEM"}, 6998a23840SMatthew Barth {0xC7, 0x03, "MAIN_PLANAR"}, 7098a23840SMatthew Barth {0xC2, 0x6F, "PowerCap"}, 71558184eaSTom Joseph {0x0b, 0xCA, "PowerSupplyRedundancy"}, 720661beb1SJayanth Othayoth {0xDA, 0x03, "TurboAllowed"}, 73558184eaSTom Joseph {0xD8, 0xC8, "PowerSupplyDerating"}, 7498a23840SMatthew Barth {0xFF, 0x00, ""}, 7598a23840SMatthew Barth }; 7698a23840SMatthew Barth 770b02be92SPatrick Venture struct sensor_data_t 780b02be92SPatrick Venture { 7998a23840SMatthew Barth uint8_t sennum; 8098a23840SMatthew Barth } __attribute__((packed)); 8198a23840SMatthew Barth 8214a47819SLei YU using SDRCacheMap = std::unordered_map<uint8_t, get_sdr::SensorDataFullRecord>; 8314a47819SLei YU SDRCacheMap sdrCacheMap __attribute__((init_priority(101))); 8414a47819SLei YU 8514a47819SLei YU using SensorThresholdMap = 8614a47819SLei YU std::unordered_map<uint8_t, get_sdr::GetSensorThresholdsResponse>; 8714a47819SLei YU SensorThresholdMap sensorThresholdMap __attribute__((init_priority(101))); 8814a47819SLei YU 89962e68baSLei YU #ifdef FEATURE_SENSORS_CACHE 90be5c6b2aSLei YU std::map<uint8_t, std::unique_ptr<sdbusplus::bus::match::match>> 91be5c6b2aSLei YU sensorAddedMatches __attribute__((init_priority(101))); 92be5c6b2aSLei YU std::map<uint8_t, std::unique_ptr<sdbusplus::bus::match::match>> 93be5c6b2aSLei YU sensorUpdatedMatches __attribute__((init_priority(101))); 94be5c6b2aSLei YU 959714050fSLei YU ipmi::sensor::SensorCacheMap sensorCacheMap __attribute__((init_priority(101))); 968c2c048eSLei YU 97be5c6b2aSLei YU void initSensorMatches() 98be5c6b2aSLei YU { 99be5c6b2aSLei YU using namespace sdbusplus::bus::match::rules; 100be5c6b2aSLei YU sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; 101be5c6b2aSLei YU for (const auto& s : ipmi::sensor::sensors) 102be5c6b2aSLei YU { 103be5c6b2aSLei YU sensorAddedMatches.emplace( 104be5c6b2aSLei YU s.first, 105be5c6b2aSLei YU std::make_unique<sdbusplus::bus::match::match>( 106be5c6b2aSLei YU bus, interfacesAdded() + argNpath(0, s.second.sensorPath), 107be5c6b2aSLei YU [id = s.first, obj = s.second.sensorPath](auto& /*msg*/) { 108be5c6b2aSLei YU // TODO 109be5c6b2aSLei YU })); 110be5c6b2aSLei YU sensorUpdatedMatches.emplace( 1119714050fSLei YU s.first, std::make_unique<sdbusplus::bus::match::match>( 112be5c6b2aSLei YU bus, 113be5c6b2aSLei YU type::signal() + path(s.second.sensorPath) + 114be5c6b2aSLei YU member("PropertiesChanged"s) + 115be5c6b2aSLei YU interface("org.freedesktop.DBus.Properties"s), 1169714050fSLei YU [&s](auto& msg) { 1179714050fSLei YU try 1189714050fSLei YU { 1199714050fSLei YU s.second.getFunc(s.first, s.second, msg); 1209714050fSLei YU } 1219714050fSLei YU catch (const std::exception& e) 1229714050fSLei YU { 1239714050fSLei YU sensorCacheMap[s.first].reset(); 1249714050fSLei YU } 125be5c6b2aSLei YU })); 126be5c6b2aSLei YU } 127be5c6b2aSLei YU } 128962e68baSLei YU #endif 129be5c6b2aSLei YU 1300b02be92SPatrick Venture int get_bus_for_path(const char* path, char** busname) 1310b02be92SPatrick Venture { 1322ae09b9aSEmily Shaffer return mapper_get_service(bus, path, busname); 1332ae09b9aSEmily Shaffer } 134d700e76aSTom 1352ae09b9aSEmily Shaffer // Use a lookup table to find the interface name of a specific sensor 1362ae09b9aSEmily Shaffer // This will be used until an alternative is found. this is the first 1372ae09b9aSEmily Shaffer // step for mapping IPMI 1380b02be92SPatrick Venture int find_openbmc_path(uint8_t num, dbus_interface_t* interface) 1390b02be92SPatrick Venture { 1402ae09b9aSEmily Shaffer int rc; 1412ae09b9aSEmily Shaffer 142db0cbe64SPatrick Venture const auto& sensor_it = ipmi::sensor::sensors.find(num); 143db0cbe64SPatrick Venture if (sensor_it == ipmi::sensor::sensors.end()) 1442ae09b9aSEmily Shaffer { 145ba23ff71SAdriana Kobylak // The sensor map does not contain the sensor requested 146ba23ff71SAdriana Kobylak return -EINVAL; 1472ae09b9aSEmily Shaffer } 1482ae09b9aSEmily Shaffer 1492ae09b9aSEmily Shaffer const auto& info = sensor_it->second; 1502ae09b9aSEmily Shaffer 1518451edf5SPatrick Williams char* busname = nullptr; 1522ae09b9aSEmily Shaffer rc = get_bus_for_path(info.sensorPath.c_str(), &busname); 1530b02be92SPatrick Venture if (rc < 0) 1540b02be92SPatrick Venture { 155b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to get %s busname: %s\n", 1560b02be92SPatrick Venture info.sensorPath.c_str(), busname); 1572ae09b9aSEmily Shaffer goto final; 1582ae09b9aSEmily Shaffer } 1592ae09b9aSEmily Shaffer 1602ae09b9aSEmily Shaffer interface->sensortype = info.sensorType; 1612ae09b9aSEmily Shaffer strcpy(interface->bus, busname); 1622ae09b9aSEmily Shaffer strcpy(interface->path, info.sensorPath.c_str()); 1632ae09b9aSEmily Shaffer // Take the interface name from the beginning of the DbusInterfaceMap. This 1642ae09b9aSEmily Shaffer // works for the Value interface but may not suffice for more complex 1652ae09b9aSEmily Shaffer // sensors. 1662ae09b9aSEmily Shaffer // tracked https://github.com/openbmc/phosphor-host-ipmid/issues/103 1670b02be92SPatrick Venture strcpy(interface->interface, 1680b02be92SPatrick Venture info.propertyInterfaces.begin()->first.c_str()); 1692ae09b9aSEmily Shaffer interface->sensornumber = num; 1702ae09b9aSEmily Shaffer 1712ae09b9aSEmily Shaffer final: 1722ae09b9aSEmily Shaffer free(busname); 1732ae09b9aSEmily Shaffer return rc; 1742ae09b9aSEmily Shaffer } 1752ae09b9aSEmily Shaffer 176d700e76aSTom ///////////////////////////////////////////////////////////////////// 177d700e76aSTom // 178d700e76aSTom // Routines used by ipmi commands wanting to interact on the dbus 179d700e76aSTom // 180d700e76aSTom ///////////////////////////////////////////////////////////////////// 1810b02be92SPatrick Venture int set_sensor_dbus_state_s(uint8_t number, const char* method, 1820b02be92SPatrick Venture const char* value) 1830b02be92SPatrick Venture { 184d700e76aSTom 185d700e76aSTom dbus_interface_t a; 186d700e76aSTom int r; 187d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 188d700e76aSTom sd_bus_message* m = NULL; 189d700e76aSTom 1902ae09b9aSEmily Shaffer r = find_openbmc_path(number, &a); 191d700e76aSTom 1920b02be92SPatrick Venture if (r < 0) 1930b02be92SPatrick Venture { 194b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); 195d700e76aSTom return 0; 196d700e76aSTom } 197d700e76aSTom 1980b02be92SPatrick Venture r = sd_bus_message_new_method_call(bus, &m, a.bus, a.path, a.interface, 1990b02be92SPatrick Venture method); 2000b02be92SPatrick Venture if (r < 0) 2010b02be92SPatrick Venture { 202b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a method call: %s", 203b51bf9c8SPatrick Venture strerror(-r)); 204d700e76aSTom goto final; 205d700e76aSTom } 206d700e76aSTom 207d700e76aSTom r = sd_bus_message_append(m, "v", "s", value); 2080b02be92SPatrick Venture if (r < 0) 2090b02be92SPatrick Venture { 210b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a input parameter: %s", 211b51bf9c8SPatrick Venture strerror(-r)); 212d700e76aSTom goto final; 213d700e76aSTom } 214d700e76aSTom 215d700e76aSTom r = sd_bus_call(bus, m, 0, &error, NULL); 2160b02be92SPatrick Venture if (r < 0) 2170b02be92SPatrick Venture { 218b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to call the method: %s", strerror(-r)); 219d700e76aSTom } 220d700e76aSTom 221d700e76aSTom final: 222d700e76aSTom sd_bus_error_free(&error); 223d700e76aSTom m = sd_bus_message_unref(m); 224d700e76aSTom 225d700e76aSTom return 0; 226d700e76aSTom } 2270b02be92SPatrick Venture int set_sensor_dbus_state_y(uint8_t number, const char* method, 2280b02be92SPatrick Venture const uint8_t value) 2290b02be92SPatrick Venture { 230d700e76aSTom 231d700e76aSTom dbus_interface_t a; 232d700e76aSTom int r; 233d700e76aSTom sd_bus_error error = SD_BUS_ERROR_NULL; 234d700e76aSTom sd_bus_message* m = NULL; 235d700e76aSTom 2362ae09b9aSEmily Shaffer r = find_openbmc_path(number, &a); 237d700e76aSTom 2380b02be92SPatrick Venture if (r < 0) 2390b02be92SPatrick Venture { 240b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to find Sensor 0x%02x\n", number); 241d700e76aSTom return 0; 242d700e76aSTom } 243d700e76aSTom 2440b02be92SPatrick Venture r = sd_bus_message_new_method_call(bus, &m, a.bus, a.path, a.interface, 2450b02be92SPatrick Venture method); 2460b02be92SPatrick Venture if (r < 0) 2470b02be92SPatrick Venture { 248b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a method call: %s", 249b51bf9c8SPatrick Venture strerror(-r)); 250d700e76aSTom goto final; 251d700e76aSTom } 252d700e76aSTom 253d700e76aSTom r = sd_bus_message_append(m, "v", "i", value); 2540b02be92SPatrick Venture if (r < 0) 2550b02be92SPatrick Venture { 256b51bf9c8SPatrick Venture std::fprintf(stderr, "Failed to create a input parameter: %s", 257b51bf9c8SPatrick Venture strerror(-r)); 258d700e76aSTom goto final; 259d700e76aSTom } 260d700e76aSTom 261d700e76aSTom r = sd_bus_call(bus, m, 0, &error, NULL); 2620b02be92SPatrick Venture if (r < 0) 2630b02be92SPatrick Venture { 264b51bf9c8SPatrick Venture std::fprintf(stderr, "12 Failed to call the method: %s", strerror(-r)); 265d700e76aSTom } 266d700e76aSTom 267d700e76aSTom final: 268d700e76aSTom sd_bus_error_free(&error); 269d700e76aSTom m = sd_bus_message_unref(m); 270d700e76aSTom 271d700e76aSTom return 0; 272d700e76aSTom } 273d700e76aSTom 2740b02be92SPatrick Venture uint8_t dbus_to_sensor_type(char* p) 2750b02be92SPatrick Venture { 27698a23840SMatthew Barth 27798a23840SMatthew Barth sensorTypemap_t* s = g_SensorTypeMap; 27898a23840SMatthew Barth char r = 0; 2790b02be92SPatrick Venture while (s->number != 0xFF) 2800b02be92SPatrick Venture { 2810b02be92SPatrick Venture if (!strcmp(s->dbusname, p)) 2820b02be92SPatrick Venture { 283558184eaSTom Joseph r = s->typecode; 28498a23840SMatthew Barth break; 28598a23840SMatthew Barth } 28698a23840SMatthew Barth s++; 28798a23840SMatthew Barth } 28898a23840SMatthew Barth 28998a23840SMatthew Barth if (s->number == 0xFF) 29098a23840SMatthew Barth printf("Failed to find Sensor Type %s\n", p); 29198a23840SMatthew Barth 29298a23840SMatthew Barth return r; 29398a23840SMatthew Barth } 29498a23840SMatthew Barth 2950b02be92SPatrick Venture uint8_t get_type_from_interface(dbus_interface_t dbus_if) 2960b02be92SPatrick Venture { 29798a23840SMatthew Barth 29856003453SBrad Bishop uint8_t type; 29998a23840SMatthew Barth 30098a23840SMatthew Barth // This is where sensors that do not exist in dbus but do 30198a23840SMatthew Barth // exist in the host code stop. This should indicate it 30298a23840SMatthew Barth // is not a supported sensor 3030b02be92SPatrick Venture if (dbus_if.interface[0] == 0) 3040b02be92SPatrick Venture { 3050b02be92SPatrick Venture return 0; 3060b02be92SPatrick Venture } 30798a23840SMatthew Barth 3087117441cSEmily Shaffer // Fetch type from interface itself. 3097117441cSEmily Shaffer if (dbus_if.sensortype != 0) 3107117441cSEmily Shaffer { 3117117441cSEmily Shaffer type = dbus_if.sensortype; 3120b02be92SPatrick Venture } 3130b02be92SPatrick Venture else 3140b02be92SPatrick Venture { 31598a23840SMatthew Barth // Non InventoryItems 3164491a46fSPatrick Venture char* p = strrchr(dbus_if.path, '/'); 31756003453SBrad Bishop type = dbus_to_sensor_type(p + 1); 31898a23840SMatthew Barth } 31998a23840SMatthew Barth 32056003453SBrad Bishop return type; 32198a23840SMatthew Barth } 32298a23840SMatthew Barth 323391f3303SEmily Shaffer // Replaces find_sensor 3240b02be92SPatrick Venture uint8_t find_type_for_sensor_number(uint8_t num) 3250b02be92SPatrick Venture { 326391f3303SEmily Shaffer int r; 327391f3303SEmily Shaffer dbus_interface_t dbus_if; 3282ae09b9aSEmily Shaffer r = find_openbmc_path(num, &dbus_if); 3290b02be92SPatrick Venture if (r < 0) 3300b02be92SPatrick Venture { 331b51bf9c8SPatrick Venture std::fprintf(stderr, "Could not find sensor %d\n", num); 33291875f77SLei YU return 0; 333391f3303SEmily Shaffer } 334391f3303SEmily Shaffer return get_type_from_interface(dbus_if); 335391f3303SEmily Shaffer } 336391f3303SEmily Shaffer 337a8be7dc8SDeepak Kumar Sahu /** 338a8be7dc8SDeepak Kumar Sahu * @brief implements the get sensor type command. 339a8be7dc8SDeepak Kumar Sahu * @param - sensorNumber 340a8be7dc8SDeepak Kumar Sahu * 341a8be7dc8SDeepak Kumar Sahu * @return IPMI completion code plus response data on success. 342a8be7dc8SDeepak Kumar Sahu * - sensorType 343a8be7dc8SDeepak Kumar Sahu * - eventType 344a8be7dc8SDeepak Kumar Sahu **/ 345a8be7dc8SDeepak Kumar Sahu 346a8be7dc8SDeepak Kumar Sahu ipmi::RspType<uint8_t, // sensorType 347a8be7dc8SDeepak Kumar Sahu uint8_t // eventType 348a8be7dc8SDeepak Kumar Sahu > 349a8be7dc8SDeepak Kumar Sahu ipmiGetSensorType(uint8_t sensorNumber) 35098a23840SMatthew Barth { 351a8be7dc8SDeepak Kumar Sahu uint8_t sensorType = find_type_for_sensor_number(sensorNumber); 35298a23840SMatthew Barth 353a8be7dc8SDeepak Kumar Sahu if (sensorType == 0) 3540b02be92SPatrick Venture { 355a8be7dc8SDeepak Kumar Sahu return ipmi::responseSensorInvalid(); 35698a23840SMatthew Barth } 35798a23840SMatthew Barth 358a8be7dc8SDeepak Kumar Sahu constexpr uint8_t eventType = 0x6F; 359a8be7dc8SDeepak Kumar Sahu return ipmi::responseSuccess(sensorType, eventType); 36098a23840SMatthew Barth } 36198a23840SMatthew Barth 3620b02be92SPatrick Venture const std::set<std::string> analogSensorInterfaces = { 363cc941e15SEmily Shaffer "xyz.openbmc_project.Sensor.Value", 364e9a64056SPatrick Venture "xyz.openbmc_project.Control.FanPwm", 365cc941e15SEmily Shaffer }; 366cc941e15SEmily Shaffer 367cc941e15SEmily Shaffer bool isAnalogSensor(const std::string& interface) 368cc941e15SEmily Shaffer { 369cc941e15SEmily Shaffer return (analogSensorInterfaces.count(interface)); 370cc941e15SEmily Shaffer } 371cc941e15SEmily Shaffer 3729da3a750SDeepak Kumar Sahu /** 3739da3a750SDeepak Kumar Sahu @brief This command is used to set sensorReading. 3749da3a750SDeepak Kumar Sahu 3759da3a750SDeepak Kumar Sahu @param 3769da3a750SDeepak Kumar Sahu - sensorNumber 3779da3a750SDeepak Kumar Sahu - operation 3789da3a750SDeepak Kumar Sahu - reading 3799da3a750SDeepak Kumar Sahu - assertOffset0_7 3809da3a750SDeepak Kumar Sahu - assertOffset8_14 3819da3a750SDeepak Kumar Sahu - deassertOffset0_7 3829da3a750SDeepak Kumar Sahu - deassertOffset8_14 3839da3a750SDeepak Kumar Sahu - eventData1 3849da3a750SDeepak Kumar Sahu - eventData2 3859da3a750SDeepak Kumar Sahu - eventData3 3869da3a750SDeepak Kumar Sahu 3879da3a750SDeepak Kumar Sahu @return completion code on success. 3889da3a750SDeepak Kumar Sahu **/ 3899da3a750SDeepak Kumar Sahu 3909da3a750SDeepak Kumar Sahu ipmi::RspType<> ipmiSetSensorReading(uint8_t sensorNumber, uint8_t operation, 3919da3a750SDeepak Kumar Sahu uint8_t reading, uint8_t assertOffset0_7, 3929da3a750SDeepak Kumar Sahu uint8_t assertOffset8_14, 3939da3a750SDeepak Kumar Sahu uint8_t deassertOffset0_7, 3949da3a750SDeepak Kumar Sahu uint8_t deassertOffset8_14, 3959da3a750SDeepak Kumar Sahu uint8_t eventData1, uint8_t eventData2, 3969da3a750SDeepak Kumar Sahu uint8_t eventData3) 397be703f71STom Joseph { 3989da3a750SDeepak Kumar Sahu log<level::DEBUG>("IPMI SET_SENSOR", 3999da3a750SDeepak Kumar Sahu entry("SENSOR_NUM=0x%02x", sensorNumber)); 4009da3a750SDeepak Kumar Sahu 4010634e989SArun P. Mohanan if (sensorNumber == 0xFF) 4020634e989SArun P. Mohanan { 4030634e989SArun P. Mohanan return ipmi::responseInvalidFieldRequest(); 4040634e989SArun P. Mohanan } 4059da3a750SDeepak Kumar Sahu ipmi::sensor::SetSensorReadingReq cmdData; 4069da3a750SDeepak Kumar Sahu 4079da3a750SDeepak Kumar Sahu cmdData.number = sensorNumber; 4089da3a750SDeepak Kumar Sahu cmdData.operation = operation; 4099da3a750SDeepak Kumar Sahu cmdData.reading = reading; 4109da3a750SDeepak Kumar Sahu cmdData.assertOffset0_7 = assertOffset0_7; 4119da3a750SDeepak Kumar Sahu cmdData.assertOffset8_14 = assertOffset8_14; 4129da3a750SDeepak Kumar Sahu cmdData.deassertOffset0_7 = deassertOffset0_7; 4139da3a750SDeepak Kumar Sahu cmdData.deassertOffset8_14 = deassertOffset8_14; 4149da3a750SDeepak Kumar Sahu cmdData.eventData1 = eventData1; 4159da3a750SDeepak Kumar Sahu cmdData.eventData2 = eventData2; 4169da3a750SDeepak Kumar Sahu cmdData.eventData3 = eventData3; 417be703f71STom Joseph 418be703f71STom Joseph // Check if the Sensor Number is present 419db0cbe64SPatrick Venture const auto iter = ipmi::sensor::sensors.find(sensorNumber); 420db0cbe64SPatrick Venture if (iter == ipmi::sensor::sensors.end()) 421be703f71STom Joseph { 4229da3a750SDeepak Kumar Sahu updateSensorRecordFromSSRAESC(&sensorNumber); 4239da3a750SDeepak Kumar Sahu return ipmi::responseSuccess(); 424be703f71STom Joseph } 425be703f71STom Joseph 42618e99992SDhruvaraj Subhashchandran try 42718e99992SDhruvaraj Subhashchandran { 4280922bde4SJayanth Othayoth if (ipmi::sensor::Mutability::Write != 4290922bde4SJayanth Othayoth (iter->second.mutability & ipmi::sensor::Mutability::Write)) 4300922bde4SJayanth Othayoth { 4310922bde4SJayanth Othayoth log<level::ERR>("Sensor Set operation is not allowed", 4329da3a750SDeepak Kumar Sahu entry("SENSOR_NUM=%d", sensorNumber)); 4339da3a750SDeepak Kumar Sahu return ipmi::responseIllegalCommand(); 4340922bde4SJayanth Othayoth } 4359da3a750SDeepak Kumar Sahu auto ipmiRC = iter->second.updateFunc(cmdData, iter->second); 4369da3a750SDeepak Kumar Sahu return ipmi::response(ipmiRC); 437be703f71STom Joseph } 438a2ad2da8SPatrick Williams catch (const InternalFailure& e) 43918e99992SDhruvaraj Subhashchandran { 44018e99992SDhruvaraj Subhashchandran log<level::ERR>("Set sensor failed", 4419da3a750SDeepak Kumar Sahu entry("SENSOR_NUM=%d", sensorNumber)); 44218e99992SDhruvaraj Subhashchandran commit<InternalFailure>(); 4439da3a750SDeepak Kumar Sahu return ipmi::responseUnspecifiedError(); 44418e99992SDhruvaraj Subhashchandran } 4458202432fSTom Joseph catch (const std::runtime_error& e) 4468202432fSTom Joseph { 4478202432fSTom Joseph log<level::ERR>(e.what()); 4489da3a750SDeepak Kumar Sahu return ipmi::responseUnspecifiedError(); 4498202432fSTom Joseph } 45098a23840SMatthew Barth } 45198a23840SMatthew Barth 4524c3feba5Sjayaprakash Mutyala /** @brief implements the get sensor reading command 4534c3feba5Sjayaprakash Mutyala * @param sensorNum - sensor number 4544c3feba5Sjayaprakash Mutyala * 4554c3feba5Sjayaprakash Mutyala * @returns IPMI completion code plus response data 4564c3feba5Sjayaprakash Mutyala * - senReading - sensor reading 4574c3feba5Sjayaprakash Mutyala * - reserved 4584c3feba5Sjayaprakash Mutyala * - readState - sensor reading state enabled 4594c3feba5Sjayaprakash Mutyala * - senScanState - sensor scan state disabled 4604c3feba5Sjayaprakash Mutyala * - allEventMessageState - all Event message state disabled 4614c3feba5Sjayaprakash Mutyala * - assertionStatesLsb - threshold levels states 4624c3feba5Sjayaprakash Mutyala * - assertionStatesMsb - discrete reading sensor states 4634c3feba5Sjayaprakash Mutyala */ 4644c3feba5Sjayaprakash Mutyala ipmi::RspType<uint8_t, // sensor reading 4653ee668f9STom Joseph 4664c3feba5Sjayaprakash Mutyala uint5_t, // reserved 4674c3feba5Sjayaprakash Mutyala bool, // reading state 4684cc42556SSui Chen bool, // 0 = sensor scanning state disabled 4694cc42556SSui Chen bool, // 0 = all event messages disabled 4704c3feba5Sjayaprakash Mutyala 4714c3feba5Sjayaprakash Mutyala uint8_t, // threshold levels states 4724c3feba5Sjayaprakash Mutyala uint8_t // discrete reading sensor states 4734c3feba5Sjayaprakash Mutyala > 4744c3feba5Sjayaprakash Mutyala ipmiSensorGetSensorReading(uint8_t sensorNum) 4754c3feba5Sjayaprakash Mutyala { 4764c3feba5Sjayaprakash Mutyala if (sensorNum == 0xFF) 4774c3feba5Sjayaprakash Mutyala { 4784c3feba5Sjayaprakash Mutyala return ipmi::responseInvalidFieldRequest(); 4794c3feba5Sjayaprakash Mutyala } 4804c3feba5Sjayaprakash Mutyala 4814c3feba5Sjayaprakash Mutyala const auto iter = ipmi::sensor::sensors.find(sensorNum); 482db0cbe64SPatrick Venture if (iter == ipmi::sensor::sensors.end()) 48314c15467STom Joseph { 4844c3feba5Sjayaprakash Mutyala return ipmi::responseSensorInvalid(); 48514c15467STom Joseph } 48613b87a3eSTom Joseph if (ipmi::sensor::Mutability::Read != 48713b87a3eSTom Joseph (iter->second.mutability & ipmi::sensor::Mutability::Read)) 48813b87a3eSTom Joseph { 4894c3feba5Sjayaprakash Mutyala return ipmi::responseIllegalCommand(); 49013b87a3eSTom Joseph } 49114c15467STom Joseph 49214c15467STom Joseph try 49314c15467STom Joseph { 4948c2c048eSLei YU #ifdef FEATURE_SENSORS_CACHE 4958c2c048eSLei YU // TODO 4969714050fSLei YU const auto& sensorData = sensorCacheMap[sensorNum]; 4979714050fSLei YU if (!sensorData.has_value()) 4989714050fSLei YU { 499*a55e9ea1SLei YU // No cached value, try read it 500*a55e9ea1SLei YU sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; 501*a55e9ea1SLei YU const auto& sensorInfo = iter->second; 502*a55e9ea1SLei YU auto service = ipmi::getService(bus, sensorInfo.sensorInterface, 503*a55e9ea1SLei YU sensorInfo.sensorPath); 504*a55e9ea1SLei YU try 505*a55e9ea1SLei YU { 506*a55e9ea1SLei YU auto method = bus.new_method_call( 507*a55e9ea1SLei YU service.c_str(), sensorInfo.sensorPath.c_str(), 508*a55e9ea1SLei YU "org.freedesktop.DBus.Properties", "GetAll"); 509*a55e9ea1SLei YU method.append( 510*a55e9ea1SLei YU sensorInfo.propertyInterfaces.begin()->first.c_str()); 511*a55e9ea1SLei YU auto reply = bus.call(method); 512*a55e9ea1SLei YU sensorInfo.getFunc(sensorNum, sensorInfo, reply); 513*a55e9ea1SLei YU } 514*a55e9ea1SLei YU catch (const std::exception& e) 515*a55e9ea1SLei YU { 516*a55e9ea1SLei YU fprintf(stderr, "Failed to get sensor %s\n", 517*a55e9ea1SLei YU sensorInfo.sensorPath.c_str()); 5189714050fSLei YU // Intitilizing with default values 5199714050fSLei YU constexpr uint8_t senReading = 0; 5209714050fSLei YU constexpr uint5_t reserved{0}; 5219714050fSLei YU constexpr bool readState = true; 5229714050fSLei YU constexpr bool senScanState = false; 5239714050fSLei YU constexpr bool allEventMessageState = false; 5249714050fSLei YU constexpr uint8_t assertionStatesLsb = 0; 5259714050fSLei YU constexpr uint8_t assertionStatesMsb = 0; 5269714050fSLei YU 527*a55e9ea1SLei YU return ipmi::responseSuccess(senReading, reserved, readState, 528*a55e9ea1SLei YU senScanState, allEventMessageState, 529*a55e9ea1SLei YU assertionStatesLsb, 530*a55e9ea1SLei YU assertionStatesMsb); 531*a55e9ea1SLei YU } 5329714050fSLei YU } 5339714050fSLei YU return ipmi::responseSuccess( 5349714050fSLei YU sensorData->response.reading, uint5_t(0), 5359714050fSLei YU sensorData->response.readingOrStateUnavailable, 5369714050fSLei YU sensorData->response.scanningEnabled, 5379714050fSLei YU sensorData->response.allEventMessagesEnabled, 5389714050fSLei YU sensorData->response.thresholdLevelsStates, 5399714050fSLei YU sensorData->response.discreteReadingSensorStates); 5409714050fSLei YU 5418c2c048eSLei YU #else 5424cc42556SSui Chen ipmi::sensor::GetSensorResponse getResponse = 5434cc42556SSui Chen iter->second.getFunc(iter->second); 5444c3feba5Sjayaprakash Mutyala 5454cc42556SSui Chen return ipmi::responseSuccess(getResponse.reading, uint5_t(0), 5464cc42556SSui Chen getResponse.readingOrStateUnavailable, 5474cc42556SSui Chen getResponse.scanningEnabled, 5484cc42556SSui Chen getResponse.allEventMessagesEnabled, 5494cc42556SSui Chen getResponse.thresholdLevelsStates, 5504cc42556SSui Chen getResponse.discreteReadingSensorStates); 5518c2c048eSLei YU #endif 55214c15467STom Joseph } 5539cf85627SBrandon Kim #ifdef UPDATE_FUNCTIONAL_ON_FAIL 5549cf85627SBrandon Kim catch (const SensorFunctionalError& e) 5559cf85627SBrandon Kim { 5564c3feba5Sjayaprakash Mutyala return ipmi::responseResponseError(); 5579cf85627SBrandon Kim } 5589cf85627SBrandon Kim #endif 5593ee668f9STom Joseph catch (const std::exception& e) 56014c15467STom Joseph { 5614c3feba5Sjayaprakash Mutyala // Intitilizing with default values 5624c3feba5Sjayaprakash Mutyala constexpr uint8_t senReading = 0; 5634c3feba5Sjayaprakash Mutyala constexpr uint5_t reserved{0}; 5644c3feba5Sjayaprakash Mutyala constexpr bool readState = true; 5654c3feba5Sjayaprakash Mutyala constexpr bool senScanState = false; 5664c3feba5Sjayaprakash Mutyala constexpr bool allEventMessageState = false; 5674c3feba5Sjayaprakash Mutyala constexpr uint8_t assertionStatesLsb = 0; 5684c3feba5Sjayaprakash Mutyala constexpr uint8_t assertionStatesMsb = 0; 5694c3feba5Sjayaprakash Mutyala 5704c3feba5Sjayaprakash Mutyala return ipmi::responseSuccess(senReading, reserved, readState, 5714c3feba5Sjayaprakash Mutyala senScanState, allEventMessageState, 5724c3feba5Sjayaprakash Mutyala assertionStatesLsb, assertionStatesMsb); 57314c15467STom Joseph } 57498a23840SMatthew Barth } 57598a23840SMatthew Barth 57689a83b67SKonstantin Aladyshev get_sdr::GetSensorThresholdsResponse 57789a83b67SKonstantin Aladyshev getSensorThresholds(ipmi::Context::ptr& ctx, uint8_t sensorNum) 5780ac0dd23STom Joseph { 579515bc375SWilliam A. Kennington III get_sdr::GetSensorThresholdsResponse resp{}; 5800ac0dd23STom Joseph constexpr auto warningThreshIntf = 5810ac0dd23STom Joseph "xyz.openbmc_project.Sensor.Threshold.Warning"; 5820ac0dd23STom Joseph constexpr auto criticalThreshIntf = 5830ac0dd23STom Joseph "xyz.openbmc_project.Sensor.Threshold.Critical"; 5840ac0dd23STom Joseph 585db0cbe64SPatrick Venture const auto iter = ipmi::sensor::sensors.find(sensorNum); 5860ac0dd23STom Joseph const auto info = iter->second; 5870ac0dd23STom Joseph 58889a83b67SKonstantin Aladyshev std::string service; 58989a83b67SKonstantin Aladyshev boost::system::error_code ec; 59089a83b67SKonstantin Aladyshev ec = ipmi::getService(ctx, info.sensorInterface, info.sensorPath, service); 59189a83b67SKonstantin Aladyshev if (ec) 59289a83b67SKonstantin Aladyshev { 59389a83b67SKonstantin Aladyshev return resp; 59489a83b67SKonstantin Aladyshev } 5950ac0dd23STom Joseph 59689a83b67SKonstantin Aladyshev ipmi::PropertyMap warnThresholds; 59789a83b67SKonstantin Aladyshev ec = ipmi::getAllDbusProperties(ctx, service, info.sensorPath, 59889a83b67SKonstantin Aladyshev warningThreshIntf, warnThresholds); 59989a83b67SKonstantin Aladyshev if (!ec) 60089a83b67SKonstantin Aladyshev { 601f442e119SVernon Mauery double warnLow = std::visit(ipmi::VariantToDoubleVisitor(), 6021e12112bSJames Feist warnThresholds["WarningLow"]); 603f442e119SVernon Mauery double warnHigh = std::visit(ipmi::VariantToDoubleVisitor(), 60437544429SJames Feist warnThresholds["WarningHigh"]); 6050ac0dd23STom Joseph 606e0a41100SKonstantin Aladyshev if (std::isfinite(warnLow)) 6070ac0dd23STom Joseph { 608586d35b4SPatrick Venture warnLow *= std::pow(10, info.scale - info.exponentR); 609996c9798Sjayaprakash Mutyala resp.lowerNonCritical = static_cast<uint8_t>( 6100b02be92SPatrick Venture (warnLow - info.scaledOffset) / info.coefficientM); 611996c9798Sjayaprakash Mutyala resp.validMask |= static_cast<uint8_t>( 6120ac0dd23STom Joseph ipmi::sensor::ThresholdMask::NON_CRITICAL_LOW_MASK); 6130ac0dd23STom Joseph } 6140ac0dd23STom Joseph 615e0a41100SKonstantin Aladyshev if (std::isfinite(warnHigh)) 6160ac0dd23STom Joseph { 617586d35b4SPatrick Venture warnHigh *= std::pow(10, info.scale - info.exponentR); 618996c9798Sjayaprakash Mutyala resp.upperNonCritical = static_cast<uint8_t>( 6190b02be92SPatrick Venture (warnHigh - info.scaledOffset) / info.coefficientM); 620996c9798Sjayaprakash Mutyala resp.validMask |= static_cast<uint8_t>( 6210ac0dd23STom Joseph ipmi::sensor::ThresholdMask::NON_CRITICAL_HIGH_MASK); 6220ac0dd23STom Joseph } 62389a83b67SKonstantin Aladyshev } 6240ac0dd23STom Joseph 62589a83b67SKonstantin Aladyshev ipmi::PropertyMap critThresholds; 62689a83b67SKonstantin Aladyshev ec = ipmi::getAllDbusProperties(ctx, service, info.sensorPath, 62789a83b67SKonstantin Aladyshev criticalThreshIntf, critThresholds); 62889a83b67SKonstantin Aladyshev if (!ec) 62989a83b67SKonstantin Aladyshev { 630f442e119SVernon Mauery double critLow = std::visit(ipmi::VariantToDoubleVisitor(), 6311e12112bSJames Feist critThresholds["CriticalLow"]); 632f442e119SVernon Mauery double critHigh = std::visit(ipmi::VariantToDoubleVisitor(), 63337544429SJames Feist critThresholds["CriticalHigh"]); 6340ac0dd23STom Joseph 635e0a41100SKonstantin Aladyshev if (std::isfinite(critLow)) 6360ac0dd23STom Joseph { 637586d35b4SPatrick Venture critLow *= std::pow(10, info.scale - info.exponentR); 638996c9798Sjayaprakash Mutyala resp.lowerCritical = static_cast<uint8_t>( 6390b02be92SPatrick Venture (critLow - info.scaledOffset) / info.coefficientM); 640996c9798Sjayaprakash Mutyala resp.validMask |= static_cast<uint8_t>( 6410ac0dd23STom Joseph ipmi::sensor::ThresholdMask::CRITICAL_LOW_MASK); 6420ac0dd23STom Joseph } 6430ac0dd23STom Joseph 644e0a41100SKonstantin Aladyshev if (std::isfinite(critHigh)) 6450ac0dd23STom Joseph { 646586d35b4SPatrick Venture critHigh *= std::pow(10, info.scale - info.exponentR); 647996c9798Sjayaprakash Mutyala resp.upperCritical = static_cast<uint8_t>( 6480b02be92SPatrick Venture (critHigh - info.scaledOffset) / info.coefficientM); 649996c9798Sjayaprakash Mutyala resp.validMask |= static_cast<uint8_t>( 6500ac0dd23STom Joseph ipmi::sensor::ThresholdMask::CRITICAL_HIGH_MASK); 6510ac0dd23STom Joseph } 65289a83b67SKonstantin Aladyshev } 653996c9798Sjayaprakash Mutyala 654996c9798Sjayaprakash Mutyala return resp; 6550ac0dd23STom Joseph } 6560ac0dd23STom Joseph 657996c9798Sjayaprakash Mutyala /** @brief implements the get sensor thresholds command 65889a83b67SKonstantin Aladyshev * @param ctx - IPMI context pointer 659996c9798Sjayaprakash Mutyala * @param sensorNum - sensor number 660996c9798Sjayaprakash Mutyala * 661996c9798Sjayaprakash Mutyala * @returns IPMI completion code plus response data 662996c9798Sjayaprakash Mutyala * - validMask - threshold mask 663996c9798Sjayaprakash Mutyala * - lower non-critical threshold - IPMI messaging state 664996c9798Sjayaprakash Mutyala * - lower critical threshold - link authentication state 665996c9798Sjayaprakash Mutyala * - lower non-recoverable threshold - callback state 666996c9798Sjayaprakash Mutyala * - upper non-critical threshold 667996c9798Sjayaprakash Mutyala * - upper critical 668996c9798Sjayaprakash Mutyala * - upper non-recoverable 669996c9798Sjayaprakash Mutyala */ 670996c9798Sjayaprakash Mutyala ipmi::RspType<uint8_t, // validMask 671996c9798Sjayaprakash Mutyala uint8_t, // lowerNonCritical 672996c9798Sjayaprakash Mutyala uint8_t, // lowerCritical 673996c9798Sjayaprakash Mutyala uint8_t, // lowerNonRecoverable 674996c9798Sjayaprakash Mutyala uint8_t, // upperNonCritical 675996c9798Sjayaprakash Mutyala uint8_t, // upperCritical 676996c9798Sjayaprakash Mutyala uint8_t // upperNonRecoverable 677996c9798Sjayaprakash Mutyala > 67889a83b67SKonstantin Aladyshev ipmiSensorGetSensorThresholds(ipmi::Context::ptr& ctx, uint8_t sensorNum) 6795c0beec1SDhruvaraj Subhashchandran { 6800ac0dd23STom Joseph constexpr auto valueInterface = "xyz.openbmc_project.Sensor.Value"; 6815c0beec1SDhruvaraj Subhashchandran 682db0cbe64SPatrick Venture const auto iter = ipmi::sensor::sensors.find(sensorNum); 683db0cbe64SPatrick Venture if (iter == ipmi::sensor::sensors.end()) 6845c0beec1SDhruvaraj Subhashchandran { 685996c9798Sjayaprakash Mutyala return ipmi::responseSensorInvalid(); 6865c0beec1SDhruvaraj Subhashchandran } 6875c0beec1SDhruvaraj Subhashchandran 6880ac0dd23STom Joseph const auto info = iter->second; 6895c0beec1SDhruvaraj Subhashchandran 6905c0beec1SDhruvaraj Subhashchandran // Proceed only if the sensor value interface is implemented. 6910ac0dd23STom Joseph if (info.propertyInterfaces.find(valueInterface) == 6920ac0dd23STom Joseph info.propertyInterfaces.end()) 6935c0beec1SDhruvaraj Subhashchandran { 6945c0beec1SDhruvaraj Subhashchandran // return with valid mask as 0 695996c9798Sjayaprakash Mutyala return ipmi::responseSuccess(); 6965c0beec1SDhruvaraj Subhashchandran } 6975c0beec1SDhruvaraj Subhashchandran 69814a47819SLei YU auto it = sensorThresholdMap.find(sensorNum); 69914a47819SLei YU if (it == sensorThresholdMap.end()) 70014a47819SLei YU { 70114a47819SLei YU sensorThresholdMap[sensorNum] = getSensorThresholds(ctx, sensorNum); 70214a47819SLei YU } 70314a47819SLei YU 70414a47819SLei YU const auto& resp = sensorThresholdMap[sensorNum]; 7055c0beec1SDhruvaraj Subhashchandran 706996c9798Sjayaprakash Mutyala return ipmi::responseSuccess(resp.validMask, resp.lowerNonCritical, 707996c9798Sjayaprakash Mutyala resp.lowerCritical, resp.lowerNonRecoverable, 708996c9798Sjayaprakash Mutyala resp.upperNonCritical, resp.upperCritical, 709996c9798Sjayaprakash Mutyala resp.upperNonRecoverable); 7105c0beec1SDhruvaraj Subhashchandran } 7115c0beec1SDhruvaraj Subhashchandran 712f93da667SLotus Xu /** @brief implements the Set Sensor threshold command 713f93da667SLotus Xu * @param sensorNumber - sensor number 714f93da667SLotus Xu * @param lowerNonCriticalThreshMask 715f93da667SLotus Xu * @param lowerCriticalThreshMask 716f93da667SLotus Xu * @param lowerNonRecovThreshMask 717f93da667SLotus Xu * @param upperNonCriticalThreshMask 718f93da667SLotus Xu * @param upperCriticalThreshMask 719f93da667SLotus Xu * @param upperNonRecovThreshMask 720f93da667SLotus Xu * @param reserved 721f93da667SLotus Xu * @param lowerNonCritical - lower non-critical threshold 722f93da667SLotus Xu * @param lowerCritical - Lower critical threshold 723f93da667SLotus Xu * @param lowerNonRecoverable - Lower non recovarable threshold 724f93da667SLotus Xu * @param upperNonCritical - Upper non-critical threshold 725f93da667SLotus Xu * @param upperCritical - Upper critical 726f93da667SLotus Xu * @param upperNonRecoverable - Upper Non-recoverable 727f93da667SLotus Xu * 728f93da667SLotus Xu * @returns IPMI completion code 729f93da667SLotus Xu */ 730f93da667SLotus Xu ipmi::RspType<> ipmiSenSetSensorThresholds( 731f93da667SLotus Xu ipmi::Context::ptr& ctx, uint8_t sensorNum, bool lowerNonCriticalThreshMask, 732f93da667SLotus Xu bool lowerCriticalThreshMask, bool lowerNonRecovThreshMask, 733f93da667SLotus Xu bool upperNonCriticalThreshMask, bool upperCriticalThreshMask, 734f93da667SLotus Xu bool upperNonRecovThreshMask, uint2_t reserved, uint8_t lowerNonCritical, 735f93da667SLotus Xu uint8_t lowerCritical, uint8_t lowerNonRecoverable, 736f93da667SLotus Xu uint8_t upperNonCritical, uint8_t upperCritical, 737f93da667SLotus Xu uint8_t upperNonRecoverable) 738f93da667SLotus Xu { 739f93da667SLotus Xu if (reserved) 740f93da667SLotus Xu { 741f93da667SLotus Xu return ipmi::responseInvalidFieldRequest(); 742f93da667SLotus Xu } 743f93da667SLotus Xu 744f93da667SLotus Xu // lower nc and upper nc not suppported on any sensor 745f93da667SLotus Xu if (lowerNonRecovThreshMask || upperNonRecovThreshMask) 746f93da667SLotus Xu { 747f93da667SLotus Xu return ipmi::responseInvalidFieldRequest(); 748f93da667SLotus Xu } 749f93da667SLotus Xu 750f93da667SLotus Xu // if none of the threshold mask are set, nothing to do 751f93da667SLotus Xu if (!(lowerNonCriticalThreshMask | lowerCriticalThreshMask | 752f93da667SLotus Xu lowerNonRecovThreshMask | upperNonCriticalThreshMask | 753f93da667SLotus Xu upperCriticalThreshMask | upperNonRecovThreshMask)) 754f93da667SLotus Xu { 755f93da667SLotus Xu return ipmi::responseSuccess(); 756f93da667SLotus Xu } 757f93da667SLotus Xu 758f93da667SLotus Xu constexpr auto valueInterface = "xyz.openbmc_project.Sensor.Value"; 759f93da667SLotus Xu 760f93da667SLotus Xu const auto iter = ipmi::sensor::sensors.find(sensorNum); 761f93da667SLotus Xu if (iter == ipmi::sensor::sensors.end()) 762f93da667SLotus Xu { 763f93da667SLotus Xu return ipmi::responseSensorInvalid(); 764f93da667SLotus Xu } 765f93da667SLotus Xu 766f93da667SLotus Xu const auto& info = iter->second; 767f93da667SLotus Xu 768f93da667SLotus Xu // Proceed only if the sensor value interface is implemented. 769f93da667SLotus Xu if (info.propertyInterfaces.find(valueInterface) == 770f93da667SLotus Xu info.propertyInterfaces.end()) 771f93da667SLotus Xu { 772f93da667SLotus Xu // return with valid mask as 0 773f93da667SLotus Xu return ipmi::responseSuccess(); 774f93da667SLotus Xu } 775f93da667SLotus Xu 776f93da667SLotus Xu constexpr auto warningThreshIntf = 777f93da667SLotus Xu "xyz.openbmc_project.Sensor.Threshold.Warning"; 778f93da667SLotus Xu constexpr auto criticalThreshIntf = 779f93da667SLotus Xu "xyz.openbmc_project.Sensor.Threshold.Critical"; 780f93da667SLotus Xu 781f93da667SLotus Xu std::string service; 782f93da667SLotus Xu boost::system::error_code ec; 783f93da667SLotus Xu ec = ipmi::getService(ctx, info.sensorInterface, info.sensorPath, service); 784f93da667SLotus Xu if (ec) 785f93da667SLotus Xu { 786f93da667SLotus Xu return ipmi::responseResponseError(); 787f93da667SLotus Xu } 788f93da667SLotus Xu // store a vector of property name, value to set, and interface 789f93da667SLotus Xu std::vector<std::tuple<std::string, uint8_t, std::string>> thresholdsToSet; 790f93da667SLotus Xu 791f93da667SLotus Xu // define the indexes of the tuple 792f93da667SLotus Xu constexpr uint8_t propertyName = 0; 793f93da667SLotus Xu constexpr uint8_t thresholdValue = 1; 794f93da667SLotus Xu constexpr uint8_t interface = 2; 795f93da667SLotus Xu // verifiy all needed fields are present 796f93da667SLotus Xu if (lowerCriticalThreshMask || upperCriticalThreshMask) 797f93da667SLotus Xu { 798f93da667SLotus Xu 799f93da667SLotus Xu ipmi::PropertyMap findThreshold; 800f93da667SLotus Xu ec = ipmi::getAllDbusProperties(ctx, service, info.sensorPath, 801f93da667SLotus Xu criticalThreshIntf, findThreshold); 802f93da667SLotus Xu 803f93da667SLotus Xu if (!ec) 804f93da667SLotus Xu { 805f93da667SLotus Xu if (lowerCriticalThreshMask) 806f93da667SLotus Xu { 807f93da667SLotus Xu auto findLower = findThreshold.find("CriticalLow"); 808f93da667SLotus Xu if (findLower == findThreshold.end()) 809f93da667SLotus Xu { 810f93da667SLotus Xu return ipmi::responseInvalidFieldRequest(); 811f93da667SLotus Xu } 812f93da667SLotus Xu thresholdsToSet.emplace_back("CriticalLow", lowerCritical, 813f93da667SLotus Xu criticalThreshIntf); 814f93da667SLotus Xu } 815f93da667SLotus Xu if (upperCriticalThreshMask) 816f93da667SLotus Xu { 817f93da667SLotus Xu auto findUpper = findThreshold.find("CriticalHigh"); 818f93da667SLotus Xu if (findUpper == findThreshold.end()) 819f93da667SLotus Xu { 820f93da667SLotus Xu return ipmi::responseInvalidFieldRequest(); 821f93da667SLotus Xu } 822f93da667SLotus Xu thresholdsToSet.emplace_back("CriticalHigh", upperCritical, 823f93da667SLotus Xu criticalThreshIntf); 824f93da667SLotus Xu } 825f93da667SLotus Xu } 826f93da667SLotus Xu } 827f93da667SLotus Xu if (lowerNonCriticalThreshMask || upperNonCriticalThreshMask) 828f93da667SLotus Xu { 829f93da667SLotus Xu ipmi::PropertyMap findThreshold; 830f93da667SLotus Xu ec = ipmi::getAllDbusProperties(ctx, service, info.sensorPath, 831f93da667SLotus Xu warningThreshIntf, findThreshold); 832f93da667SLotus Xu 833f93da667SLotus Xu if (!ec) 834f93da667SLotus Xu { 835f93da667SLotus Xu if (lowerNonCriticalThreshMask) 836f93da667SLotus Xu { 837f93da667SLotus Xu auto findLower = findThreshold.find("WarningLow"); 838f93da667SLotus Xu if (findLower == findThreshold.end()) 839f93da667SLotus Xu { 840f93da667SLotus Xu return ipmi::responseInvalidFieldRequest(); 841f93da667SLotus Xu } 842f93da667SLotus Xu thresholdsToSet.emplace_back("WarningLow", lowerNonCritical, 843f93da667SLotus Xu warningThreshIntf); 844f93da667SLotus Xu } 845f93da667SLotus Xu if (upperNonCriticalThreshMask) 846f93da667SLotus Xu { 847f93da667SLotus Xu auto findUpper = findThreshold.find("WarningHigh"); 848f93da667SLotus Xu if (findUpper == findThreshold.end()) 849f93da667SLotus Xu { 850f93da667SLotus Xu return ipmi::responseInvalidFieldRequest(); 851f93da667SLotus Xu } 852f93da667SLotus Xu thresholdsToSet.emplace_back("WarningHigh", upperNonCritical, 853f93da667SLotus Xu warningThreshIntf); 854f93da667SLotus Xu } 855f93da667SLotus Xu } 856f93da667SLotus Xu } 857f93da667SLotus Xu for (const auto& property : thresholdsToSet) 858f93da667SLotus Xu { 859f93da667SLotus Xu // from section 36.3 in the IPMI Spec, assume all linear 860f93da667SLotus Xu double valueToSet = 861f93da667SLotus Xu ((info.coefficientM * std::get<thresholdValue>(property)) + 862f93da667SLotus Xu (info.scaledOffset * std::pow(10.0, info.scale))) * 863f93da667SLotus Xu std::pow(10.0, info.exponentR); 864f93da667SLotus Xu ipmi::setDbusProperty( 865f93da667SLotus Xu ctx, service, info.sensorPath, std::get<interface>(property), 866f93da667SLotus Xu std::get<propertyName>(property), ipmi::Value(valueToSet)); 867f93da667SLotus Xu } 868f93da667SLotus Xu 86914a47819SLei YU // Invalidate the cache 87014a47819SLei YU sensorThresholdMap.erase(sensorNum); 871f93da667SLotus Xu return ipmi::responseSuccess(); 872f93da667SLotus Xu } 873f93da667SLotus Xu 874d957823eSjayaprakash Mutyala /** @brief implements the get SDR Info command 875d957823eSjayaprakash Mutyala * @param count - Operation 876d957823eSjayaprakash Mutyala * 877d957823eSjayaprakash Mutyala * @returns IPMI completion code plus response data 878d957823eSjayaprakash Mutyala * - sdrCount - sensor/SDR count 879d957823eSjayaprakash Mutyala * - lunsAndDynamicPopulation - static/Dynamic sensor population flag 880d957823eSjayaprakash Mutyala */ 881d957823eSjayaprakash Mutyala ipmi::RspType<uint8_t, // respcount 882d957823eSjayaprakash Mutyala uint8_t // dynamic population flags 883d957823eSjayaprakash Mutyala > 884d957823eSjayaprakash Mutyala ipmiSensorGetDeviceSdrInfo(std::optional<uint8_t> count) 885d06e0e7eSEmily Shaffer { 886d957823eSjayaprakash Mutyala uint8_t sdrCount; 887d957823eSjayaprakash Mutyala // multiple LUNs not supported. 888d957823eSjayaprakash Mutyala constexpr uint8_t lunsAndDynamicPopulation = 1; 889d957823eSjayaprakash Mutyala constexpr uint8_t getSdrCount = 0x01; 890d957823eSjayaprakash Mutyala constexpr uint8_t getSensorCount = 0x00; 891d957823eSjayaprakash Mutyala 892d957823eSjayaprakash Mutyala if (count.value_or(0) == getSdrCount) 893d06e0e7eSEmily Shaffer { 894d957823eSjayaprakash Mutyala // Get SDR count. This returns the total number of SDRs in the device. 89587fd2cd1SPatrick Venture const auto& entityRecords = 89687fd2cd1SPatrick Venture ipmi::sensor::EntityInfoMapContainer::getContainer() 89787fd2cd1SPatrick Venture ->getIpmiEntityRecords(); 898db0cbe64SPatrick Venture sdrCount = 899db0cbe64SPatrick Venture ipmi::sensor::sensors.size() + frus.size() + entityRecords.size(); 900d957823eSjayaprakash Mutyala } 901d957823eSjayaprakash Mutyala else if (count.value_or(0) == getSensorCount) 902d957823eSjayaprakash Mutyala { 903d957823eSjayaprakash Mutyala // Get Sensor count. This returns the number of sensors 904db0cbe64SPatrick Venture sdrCount = ipmi::sensor::sensors.size(); 905d06e0e7eSEmily Shaffer } 906d06e0e7eSEmily Shaffer else 907d06e0e7eSEmily Shaffer { 908d957823eSjayaprakash Mutyala return ipmi::responseInvalidCommandOnLun(); 909d06e0e7eSEmily Shaffer } 910d06e0e7eSEmily Shaffer 911d957823eSjayaprakash Mutyala return ipmi::responseSuccess(sdrCount, lunsAndDynamicPopulation); 912d06e0e7eSEmily Shaffer } 913d06e0e7eSEmily Shaffer 914d957823eSjayaprakash Mutyala /** @brief implements the reserve SDR command 915d957823eSjayaprakash Mutyala * @returns IPMI completion code plus response data 916d957823eSjayaprakash Mutyala * - reservationID - reservation ID 917d957823eSjayaprakash Mutyala */ 918d957823eSjayaprakash Mutyala ipmi::RspType<uint16_t> ipmiSensorReserveSdr() 919a344afc0SEmily Shaffer { 920a344afc0SEmily Shaffer // A constant reservation ID is okay until we implement add/remove SDR. 921d957823eSjayaprakash Mutyala constexpr uint16_t reservationID = 1; 922a344afc0SEmily Shaffer 923d957823eSjayaprakash Mutyala return ipmi::responseSuccess(reservationID); 924a344afc0SEmily Shaffer } 92598a23840SMatthew Barth 926dc212b23STom Joseph void setUnitFieldsForObject(const ipmi::sensor::Info* info, 927cc941e15SEmily Shaffer get_sdr::SensorDataFullRecordBody* body) 928bbef71c2SEmily Shaffer { 929bbef71c2SEmily Shaffer namespace server = sdbusplus::xyz::openbmc_project::Sensor::server; 930dc212b23STom Joseph try 931dc212b23STom Joseph { 932dc212b23STom Joseph auto unit = server::Value::convertUnitFromString(info->unit); 933bbef71c2SEmily Shaffer // Unit strings defined in 934bbef71c2SEmily Shaffer // phosphor-dbus-interfaces/xyz/openbmc_project/Sensor/Value.interface.yaml 935bbef71c2SEmily Shaffer switch (unit) 936bbef71c2SEmily Shaffer { 937bbef71c2SEmily Shaffer case server::Value::Unit::DegreesC: 938bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_DEGREES_C; 939bbef71c2SEmily Shaffer break; 940bbef71c2SEmily Shaffer case server::Value::Unit::RPMS: 941812e44c7SKirill Pakhomov body->sensor_units_2_base = get_sdr::SENSOR_UNIT_RPM; 942bbef71c2SEmily Shaffer break; 943bbef71c2SEmily Shaffer case server::Value::Unit::Volts: 944bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_VOLTS; 945bbef71c2SEmily Shaffer break; 946bbef71c2SEmily Shaffer case server::Value::Unit::Meters: 947bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_METERS; 948bbef71c2SEmily Shaffer break; 949bbef71c2SEmily Shaffer case server::Value::Unit::Amperes: 950bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_AMPERES; 951bbef71c2SEmily Shaffer break; 952bbef71c2SEmily Shaffer case server::Value::Unit::Joules: 953bbef71c2SEmily Shaffer body->sensor_units_2_base = get_sdr::SENSOR_UNIT_JOULES; 954bbef71c2SEmily Shaffer break; 955dc212b23STom Joseph case server::Value::Unit::Watts: 956dc212b23STom Joseph body->sensor_units_2_base = get_sdr::SENSOR_UNIT_WATTS; 957dc212b23STom Joseph break; 958bbef71c2SEmily Shaffer default: 959cc941e15SEmily Shaffer // Cannot be hit. 960b51bf9c8SPatrick Venture std::fprintf(stderr, "Unknown value unit type: = %s\n", 961dc212b23STom Joseph info->unit.c_str()); 962cc941e15SEmily Shaffer } 963cc941e15SEmily Shaffer } 96464678b85SPatrick Venture catch (const sdbusplus::exception::InvalidEnumString& e) 965cc941e15SEmily Shaffer { 966cc941e15SEmily Shaffer log<level::WARNING>("Warning: no unit provided for sensor!"); 967cc941e15SEmily Shaffer } 968cc941e15SEmily Shaffer } 969cc941e15SEmily Shaffer 970cc941e15SEmily Shaffer ipmi_ret_t populate_record_from_dbus(get_sdr::SensorDataFullRecordBody* body, 971cc941e15SEmily Shaffer const ipmi::sensor::Info* info, 972cc941e15SEmily Shaffer ipmi_data_len_t data_len) 973cc941e15SEmily Shaffer { 974cc941e15SEmily Shaffer /* Functional sensor case */ 975cc941e15SEmily Shaffer if (isAnalogSensor(info->propertyInterfaces.begin()->first)) 976cc941e15SEmily Shaffer { 977c5324251STony Lee body->sensor_units_1 = info->sensorUnits1; // default is 0. unsigned, no 978c5324251STony Lee // rate, no modifier, not a % 979cc941e15SEmily Shaffer /* Unit info */ 980dc212b23STom Joseph setUnitFieldsForObject(info, body); 98110f4959aSEmily Shaffer 98210f4959aSEmily Shaffer get_sdr::body::set_b(info->coefficientB, body); 98310f4959aSEmily Shaffer get_sdr::body::set_m(info->coefficientM, body); 98410f4959aSEmily Shaffer get_sdr::body::set_b_exp(info->exponentB, body); 985dc212b23STom Joseph get_sdr::body::set_r_exp(info->exponentR, body); 986bbef71c2SEmily Shaffer 987bbef71c2SEmily Shaffer get_sdr::body::set_id_type(0b00, body); // 00 = unicode 9889642391dSTom Joseph } 9899642391dSTom Joseph 9909642391dSTom Joseph /* ID string */ 991be4ffa87SJeremy Kerr auto id_string = info->sensorName; 992be4ffa87SJeremy Kerr 993be4ffa87SJeremy Kerr if (id_string.empty()) 994be4ffa87SJeremy Kerr { 995be4ffa87SJeremy Kerr id_string = info->sensorNameFunc(*info); 996be4ffa87SJeremy Kerr } 9979642391dSTom Joseph 998bbef71c2SEmily Shaffer if (id_string.length() > FULL_RECORD_ID_STR_MAX_LENGTH) 999bbef71c2SEmily Shaffer { 1000bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(FULL_RECORD_ID_STR_MAX_LENGTH, body); 1001bbef71c2SEmily Shaffer } 1002bbef71c2SEmily Shaffer else 1003bbef71c2SEmily Shaffer { 1004bbef71c2SEmily Shaffer get_sdr::body::set_id_strlen(id_string.length(), body); 1005bbef71c2SEmily Shaffer } 1006bbef71c2SEmily Shaffer strncpy(body->id_string, id_string.c_str(), 1007bbef71c2SEmily Shaffer get_sdr::body::get_id_strlen(body)); 1008bbef71c2SEmily Shaffer 1009bbef71c2SEmily Shaffer return IPMI_CC_OK; 1010bbef71c2SEmily Shaffer }; 1011bbef71c2SEmily Shaffer 1012e0cc8553SRatan Gupta ipmi_ret_t ipmi_fru_get_sdr(ipmi_request_t request, ipmi_response_t response, 1013e0cc8553SRatan Gupta ipmi_data_len_t data_len) 1014e0cc8553SRatan Gupta { 1015e0cc8553SRatan Gupta auto req = reinterpret_cast<get_sdr::GetSdrReq*>(request); 1016e0cc8553SRatan Gupta auto resp = reinterpret_cast<get_sdr::GetSdrResp*>(response); 1017e0cc8553SRatan Gupta get_sdr::SensorDataFruRecord record{}; 1018e0cc8553SRatan Gupta auto dataLength = 0; 1019e0cc8553SRatan Gupta 1020e0cc8553SRatan Gupta auto fru = frus.begin(); 1021e0cc8553SRatan Gupta uint8_t fruID{}; 1022e0cc8553SRatan Gupta auto recordID = get_sdr::request::get_record_id(req); 1023e0cc8553SRatan Gupta 1024e0cc8553SRatan Gupta fruID = recordID - FRU_RECORD_ID_START; 1025e0cc8553SRatan Gupta fru = frus.find(fruID); 1026e0cc8553SRatan Gupta if (fru == frus.end()) 1027e0cc8553SRatan Gupta { 1028e0cc8553SRatan Gupta return IPMI_CC_SENSOR_INVALID; 1029e0cc8553SRatan Gupta } 1030e0cc8553SRatan Gupta 1031e0cc8553SRatan Gupta /* Header */ 1032e0cc8553SRatan Gupta get_sdr::header::set_record_id(recordID, &(record.header)); 1033e0cc8553SRatan Gupta record.header.sdr_version = SDR_VERSION; // Based on IPMI Spec v2.0 rev 1.1 1034e0cc8553SRatan Gupta record.header.record_type = get_sdr::SENSOR_DATA_FRU_RECORD; 1035e0cc8553SRatan Gupta record.header.record_length = sizeof(record.key) + sizeof(record.body); 1036e0cc8553SRatan Gupta 1037e0cc8553SRatan Gupta /* Key */ 1038e0cc8553SRatan Gupta record.key.fruID = fruID; 1039e0cc8553SRatan Gupta record.key.accessLun |= IPMI_LOGICAL_FRU; 1040e0cc8553SRatan Gupta record.key.deviceAddress = BMCSlaveAddress; 1041e0cc8553SRatan Gupta 1042e0cc8553SRatan Gupta /* Body */ 1043e0cc8553SRatan Gupta record.body.entityID = fru->second[0].entityID; 1044e0cc8553SRatan Gupta record.body.entityInstance = fru->second[0].entityInstance; 1045e0cc8553SRatan Gupta record.body.deviceType = fruInventoryDevice; 1046e0cc8553SRatan Gupta record.body.deviceTypeModifier = IPMIFruInventory; 1047e0cc8553SRatan Gupta 1048e0cc8553SRatan Gupta /* Device ID string */ 10490b02be92SPatrick Venture auto deviceID = 10500b02be92SPatrick Venture fru->second[0].path.substr(fru->second[0].path.find_last_of('/') + 1, 1051e0cc8553SRatan Gupta fru->second[0].path.length()); 1052e0cc8553SRatan Gupta 1053e0cc8553SRatan Gupta if (deviceID.length() > get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH) 1054e0cc8553SRatan Gupta { 1055e0cc8553SRatan Gupta get_sdr::body::set_device_id_strlen( 10560b02be92SPatrick Venture get_sdr::FRU_RECORD_DEVICE_ID_MAX_LENGTH, &(record.body)); 1057e0cc8553SRatan Gupta } 1058e0cc8553SRatan Gupta else 1059e0cc8553SRatan Gupta { 10600b02be92SPatrick Venture get_sdr::body::set_device_id_strlen(deviceID.length(), &(record.body)); 1061e0cc8553SRatan Gupta } 1062e0cc8553SRatan Gupta 1063e0cc8553SRatan Gupta strncpy(record.body.deviceID, deviceID.c_str(), 1064e0cc8553SRatan Gupta get_sdr::body::get_device_id_strlen(&(record.body))); 1065e0cc8553SRatan Gupta 1066e0cc8553SRatan Gupta if (++fru == frus.end()) 1067e0cc8553SRatan Gupta { 10689c11894eSJaghathiswari Rankappagounder Natarajan // we have reached till end of fru, so assign the next record id to 10699c11894eSJaghathiswari Rankappagounder Natarajan // 512(Max fru ID = 511) + Entity Record ID(may start with 0). 107087fd2cd1SPatrick Venture const auto& entityRecords = 107187fd2cd1SPatrick Venture ipmi::sensor::EntityInfoMapContainer::getContainer() 107287fd2cd1SPatrick Venture ->getIpmiEntityRecords(); 10739c11894eSJaghathiswari Rankappagounder Natarajan auto next_record_id = 107483a0b848SPatrick Venture (entityRecords.size()) 107583a0b848SPatrick Venture ? entityRecords.begin()->first + ENTITY_RECORD_ID_START 10769c11894eSJaghathiswari Rankappagounder Natarajan : END_OF_RECORD; 10779c11894eSJaghathiswari Rankappagounder Natarajan get_sdr::response::set_next_record_id(next_record_id, resp); 10789c11894eSJaghathiswari Rankappagounder Natarajan } 10799c11894eSJaghathiswari Rankappagounder Natarajan else 10809c11894eSJaghathiswari Rankappagounder Natarajan { 10819c11894eSJaghathiswari Rankappagounder Natarajan get_sdr::response::set_next_record_id( 10829c11894eSJaghathiswari Rankappagounder Natarajan (FRU_RECORD_ID_START + fru->first), resp); 10839c11894eSJaghathiswari Rankappagounder Natarajan } 10849c11894eSJaghathiswari Rankappagounder Natarajan 10859c11894eSJaghathiswari Rankappagounder Natarajan // Check for invalid offset size 10869c11894eSJaghathiswari Rankappagounder Natarajan if (req->offset > sizeof(record)) 10879c11894eSJaghathiswari Rankappagounder Natarajan { 10889c11894eSJaghathiswari Rankappagounder Natarajan return IPMI_CC_PARM_OUT_OF_RANGE; 10899c11894eSJaghathiswari Rankappagounder Natarajan } 10909c11894eSJaghathiswari Rankappagounder Natarajan 10919c11894eSJaghathiswari Rankappagounder Natarajan dataLength = std::min(static_cast<size_t>(req->bytes_to_read), 10929c11894eSJaghathiswari Rankappagounder Natarajan sizeof(record) - req->offset); 10939c11894eSJaghathiswari Rankappagounder Natarajan 10949c11894eSJaghathiswari Rankappagounder Natarajan std::memcpy(resp->record_data, 10959c11894eSJaghathiswari Rankappagounder Natarajan reinterpret_cast<uint8_t*>(&record) + req->offset, dataLength); 10969c11894eSJaghathiswari Rankappagounder Natarajan 10979c11894eSJaghathiswari Rankappagounder Natarajan *data_len = dataLength; 10989c11894eSJaghathiswari Rankappagounder Natarajan *data_len += 2; // additional 2 bytes for next record ID 10999c11894eSJaghathiswari Rankappagounder Natarajan 11009c11894eSJaghathiswari Rankappagounder Natarajan return IPMI_CC_OK; 11019c11894eSJaghathiswari Rankappagounder Natarajan } 11029c11894eSJaghathiswari Rankappagounder Natarajan 11039c11894eSJaghathiswari Rankappagounder Natarajan ipmi_ret_t ipmi_entity_get_sdr(ipmi_request_t request, ipmi_response_t response, 11049c11894eSJaghathiswari Rankappagounder Natarajan ipmi_data_len_t data_len) 11059c11894eSJaghathiswari Rankappagounder Natarajan { 11069c11894eSJaghathiswari Rankappagounder Natarajan auto req = reinterpret_cast<get_sdr::GetSdrReq*>(request); 11079c11894eSJaghathiswari Rankappagounder Natarajan auto resp = reinterpret_cast<get_sdr::GetSdrResp*>(response); 11089c11894eSJaghathiswari Rankappagounder Natarajan get_sdr::SensorDataEntityRecord record{}; 11099c11894eSJaghathiswari Rankappagounder Natarajan auto dataLength = 0; 11109c11894eSJaghathiswari Rankappagounder Natarajan 111187fd2cd1SPatrick Venture const auto& entityRecords = 111287fd2cd1SPatrick Venture ipmi::sensor::EntityInfoMapContainer::getContainer() 111387fd2cd1SPatrick Venture ->getIpmiEntityRecords(); 111483a0b848SPatrick Venture auto entity = entityRecords.begin(); 11159c11894eSJaghathiswari Rankappagounder Natarajan uint8_t entityRecordID; 11169c11894eSJaghathiswari Rankappagounder Natarajan auto recordID = get_sdr::request::get_record_id(req); 11179c11894eSJaghathiswari Rankappagounder Natarajan 11189c11894eSJaghathiswari Rankappagounder Natarajan entityRecordID = recordID - ENTITY_RECORD_ID_START; 111983a0b848SPatrick Venture entity = entityRecords.find(entityRecordID); 112083a0b848SPatrick Venture if (entity == entityRecords.end()) 11219c11894eSJaghathiswari Rankappagounder Natarajan { 11229c11894eSJaghathiswari Rankappagounder Natarajan return IPMI_CC_SENSOR_INVALID; 11239c11894eSJaghathiswari Rankappagounder Natarajan } 11249c11894eSJaghathiswari Rankappagounder Natarajan 11259c11894eSJaghathiswari Rankappagounder Natarajan /* Header */ 11269c11894eSJaghathiswari Rankappagounder Natarajan get_sdr::header::set_record_id(recordID, &(record.header)); 11279c11894eSJaghathiswari Rankappagounder Natarajan record.header.sdr_version = SDR_VERSION; // Based on IPMI Spec v2.0 rev 1.1 11289c11894eSJaghathiswari Rankappagounder Natarajan record.header.record_type = get_sdr::SENSOR_DATA_ENTITY_RECORD; 11299c11894eSJaghathiswari Rankappagounder Natarajan record.header.record_length = sizeof(record.key) + sizeof(record.body); 11309c11894eSJaghathiswari Rankappagounder Natarajan 11319c11894eSJaghathiswari Rankappagounder Natarajan /* Key */ 11329c11894eSJaghathiswari Rankappagounder Natarajan record.key.containerEntityId = entity->second.containerEntityId; 11339c11894eSJaghathiswari Rankappagounder Natarajan record.key.containerEntityInstance = entity->second.containerEntityInstance; 11349c11894eSJaghathiswari Rankappagounder Natarajan get_sdr::key::set_flags(entity->second.isList, entity->second.isLinked, 11359c11894eSJaghathiswari Rankappagounder Natarajan &(record.key)); 11369c11894eSJaghathiswari Rankappagounder Natarajan record.key.entityId1 = entity->second.containedEntities[0].first; 11379c11894eSJaghathiswari Rankappagounder Natarajan record.key.entityInstance1 = entity->second.containedEntities[0].second; 11389c11894eSJaghathiswari Rankappagounder Natarajan 11399c11894eSJaghathiswari Rankappagounder Natarajan /* Body */ 11409c11894eSJaghathiswari Rankappagounder Natarajan record.body.entityId2 = entity->second.containedEntities[1].first; 11419c11894eSJaghathiswari Rankappagounder Natarajan record.body.entityInstance2 = entity->second.containedEntities[1].second; 11429c11894eSJaghathiswari Rankappagounder Natarajan record.body.entityId3 = entity->second.containedEntities[2].first; 11439c11894eSJaghathiswari Rankappagounder Natarajan record.body.entityInstance3 = entity->second.containedEntities[2].second; 11449c11894eSJaghathiswari Rankappagounder Natarajan record.body.entityId4 = entity->second.containedEntities[3].first; 11459c11894eSJaghathiswari Rankappagounder Natarajan record.body.entityInstance4 = entity->second.containedEntities[3].second; 11469c11894eSJaghathiswari Rankappagounder Natarajan 114783a0b848SPatrick Venture if (++entity == entityRecords.end()) 11489c11894eSJaghathiswari Rankappagounder Natarajan { 11490b02be92SPatrick Venture get_sdr::response::set_next_record_id(END_OF_RECORD, 11500b02be92SPatrick Venture resp); // last record 1151e0cc8553SRatan Gupta } 1152e0cc8553SRatan Gupta else 1153e0cc8553SRatan Gupta { 1154e0cc8553SRatan Gupta get_sdr::response::set_next_record_id( 11559c11894eSJaghathiswari Rankappagounder Natarajan (ENTITY_RECORD_ID_START + entity->first), resp); 1156e0cc8553SRatan Gupta } 1157e0cc8553SRatan Gupta 11580fbdbce2SEmily Shaffer // Check for invalid offset size 11590fbdbce2SEmily Shaffer if (req->offset > sizeof(record)) 1160e0cc8553SRatan Gupta { 11610fbdbce2SEmily Shaffer return IPMI_CC_PARM_OUT_OF_RANGE; 1162e0cc8553SRatan Gupta } 1163e0cc8553SRatan Gupta 11640fbdbce2SEmily Shaffer dataLength = std::min(static_cast<size_t>(req->bytes_to_read), 11650fbdbce2SEmily Shaffer sizeof(record) - req->offset); 1166e0cc8553SRatan Gupta 1167b51bf9c8SPatrick Venture std::memcpy(resp->record_data, 11681cd85963SJason M. Bills reinterpret_cast<uint8_t*>(&record) + req->offset, dataLength); 1169e0cc8553SRatan Gupta 1170e0cc8553SRatan Gupta *data_len = dataLength; 1171e0cc8553SRatan Gupta *data_len += 2; // additional 2 bytes for next record ID 1172e0cc8553SRatan Gupta 1173e0cc8553SRatan Gupta return IPMI_CC_OK; 1174e0cc8553SRatan Gupta } 1175e0cc8553SRatan Gupta 1176bbef71c2SEmily Shaffer ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 1177bbef71c2SEmily Shaffer ipmi_request_t request, ipmi_response_t response, 1178bbef71c2SEmily Shaffer ipmi_data_len_t data_len, ipmi_context_t context) 1179bbef71c2SEmily Shaffer { 1180bbef71c2SEmily Shaffer ipmi_ret_t ret = IPMI_CC_OK; 1181bbef71c2SEmily Shaffer get_sdr::GetSdrReq* req = (get_sdr::GetSdrReq*)request; 1182bbef71c2SEmily Shaffer get_sdr::GetSdrResp* resp = (get_sdr::GetSdrResp*)response; 118338426dd5SPatrick Venture 1184bbef71c2SEmily Shaffer // Note: we use an iterator so we can provide the next ID at the end of 1185bbef71c2SEmily Shaffer // the call. 1186db0cbe64SPatrick Venture auto sensor = ipmi::sensor::sensors.begin(); 1187e0cc8553SRatan Gupta auto recordID = get_sdr::request::get_record_id(req); 1188bbef71c2SEmily Shaffer 1189bbef71c2SEmily Shaffer // At the beginning of a scan, the host side will send us id=0. 1190e0cc8553SRatan Gupta if (recordID != 0) 1191bbef71c2SEmily Shaffer { 11929c11894eSJaghathiswari Rankappagounder Natarajan // recordID 0 to 255 means it is a FULL record. 11939c11894eSJaghathiswari Rankappagounder Natarajan // recordID 256 to 511 means it is a FRU record. 11949c11894eSJaghathiswari Rankappagounder Natarajan // recordID greater then 511 means it is a Entity Association 11959c11894eSJaghathiswari Rankappagounder Natarajan // record. Currently we are supporting three record types: FULL 11969c11894eSJaghathiswari Rankappagounder Natarajan // record, FRU record and Enttiy Association record. 11979c11894eSJaghathiswari Rankappagounder Natarajan if (recordID >= ENTITY_RECORD_ID_START) 11989c11894eSJaghathiswari Rankappagounder Natarajan { 11999c11894eSJaghathiswari Rankappagounder Natarajan return ipmi_entity_get_sdr(request, response, data_len); 12009c11894eSJaghathiswari Rankappagounder Natarajan } 12019c11894eSJaghathiswari Rankappagounder Natarajan else if (recordID >= FRU_RECORD_ID_START && 12029c11894eSJaghathiswari Rankappagounder Natarajan recordID < ENTITY_RECORD_ID_START) 1203e0cc8553SRatan Gupta { 1204e0cc8553SRatan Gupta return ipmi_fru_get_sdr(request, response, data_len); 1205e0cc8553SRatan Gupta } 1206e0cc8553SRatan Gupta else 1207e0cc8553SRatan Gupta { 1208db0cbe64SPatrick Venture sensor = ipmi::sensor::sensors.find(recordID); 1209db0cbe64SPatrick Venture if (sensor == ipmi::sensor::sensors.end()) 1210e0cc8553SRatan Gupta { 1211bbef71c2SEmily Shaffer return IPMI_CC_SENSOR_INVALID; 1212bbef71c2SEmily Shaffer } 1213bbef71c2SEmily Shaffer } 1214e0cc8553SRatan Gupta } 1215bbef71c2SEmily Shaffer 1216bbef71c2SEmily Shaffer uint8_t sensor_id = sensor->first; 1217bbef71c2SEmily Shaffer 121814a47819SLei YU auto it = sdrCacheMap.find(sensor_id); 121914a47819SLei YU if (it == sdrCacheMap.end()) 122014a47819SLei YU { 1221bbef71c2SEmily Shaffer /* Header */ 122214a47819SLei YU get_sdr::SensorDataFullRecord record = {0}; 1223bbef71c2SEmily Shaffer get_sdr::header::set_record_id(sensor_id, &(record.header)); 1224bbef71c2SEmily Shaffer record.header.sdr_version = 0x51; // Based on IPMI Spec v2.0 rev 1.1 1225bbef71c2SEmily Shaffer record.header.record_type = get_sdr::SENSOR_DATA_FULL_RECORD; 1226158ac703SPatrick Venture record.header.record_length = sizeof(record.key) + sizeof(record.body); 1227bbef71c2SEmily Shaffer 1228bbef71c2SEmily Shaffer /* Key */ 12299642391dSTom Joseph get_sdr::key::set_owner_id_bmc(&(record.key)); 1230bbef71c2SEmily Shaffer record.key.sensor_number = sensor_id; 1231bbef71c2SEmily Shaffer 1232bbef71c2SEmily Shaffer /* Body */ 12339642391dSTom Joseph record.body.entity_id = sensor->second.entityType; 1234bbef71c2SEmily Shaffer record.body.sensor_type = sensor->second.sensorType; 1235bbef71c2SEmily Shaffer record.body.event_reading_type = sensor->second.sensorReadingType; 12369642391dSTom Joseph record.body.entity_instance = sensor->second.instance; 12370780df10SJaghathiswari Rankappagounder Natarajan if (ipmi::sensor::Mutability::Write == 12380780df10SJaghathiswari Rankappagounder Natarajan (sensor->second.mutability & ipmi::sensor::Mutability::Write)) 12390780df10SJaghathiswari Rankappagounder Natarajan { 12400780df10SJaghathiswari Rankappagounder Natarajan get_sdr::body::init_settable_state(true, &(record.body)); 12410780df10SJaghathiswari Rankappagounder Natarajan } 1242bbef71c2SEmily Shaffer 1243bbef71c2SEmily Shaffer // Set the type-specific details given the DBus interface 124438426dd5SPatrick Venture populate_record_from_dbus(&(record.body), &(sensor->second), data_len); 124514a47819SLei YU sdrCacheMap[sensor_id] = std::move(record); 124614a47819SLei YU } 124714a47819SLei YU 124814a47819SLei YU const auto& record = sdrCacheMap[sensor_id]; 1249bbef71c2SEmily Shaffer 1250db0cbe64SPatrick Venture if (++sensor == ipmi::sensor::sensors.end()) 1251bbef71c2SEmily Shaffer { 1252e0cc8553SRatan Gupta // we have reached till end of sensor, so assign the next record id 1253e0cc8553SRatan Gupta // to 256(Max Sensor ID = 255) + FRU ID(may start with 0). 125438426dd5SPatrick Venture auto next_record_id = (frus.size()) 125538426dd5SPatrick Venture ? frus.begin()->first + FRU_RECORD_ID_START 12560b02be92SPatrick Venture : END_OF_RECORD; 1257e0cc8553SRatan Gupta 1258e0cc8553SRatan Gupta get_sdr::response::set_next_record_id(next_record_id, resp); 1259bbef71c2SEmily Shaffer } 1260bbef71c2SEmily Shaffer else 1261bbef71c2SEmily Shaffer { 1262bbef71c2SEmily Shaffer get_sdr::response::set_next_record_id(sensor->first, resp); 1263bbef71c2SEmily Shaffer } 1264bbef71c2SEmily Shaffer 12656c9ee519SEmily Shaffer if (req->offset > sizeof(record)) 12666c9ee519SEmily Shaffer { 12676c9ee519SEmily Shaffer return IPMI_CC_PARM_OUT_OF_RANGE; 12686c9ee519SEmily Shaffer } 12696c9ee519SEmily Shaffer 12706c9ee519SEmily Shaffer // data_len will ultimately be the size of the record, plus 12716c9ee519SEmily Shaffer // the size of the next record ID: 12726c9ee519SEmily Shaffer *data_len = std::min(static_cast<size_t>(req->bytes_to_read), 12736c9ee519SEmily Shaffer sizeof(record) - req->offset); 12746c9ee519SEmily Shaffer 12756c9ee519SEmily Shaffer std::memcpy(resp->record_data, 127614a47819SLei YU reinterpret_cast<const uint8_t*>(&record) + req->offset, 127714a47819SLei YU *data_len); 12786c9ee519SEmily Shaffer 12796c9ee519SEmily Shaffer // data_len should include the LSB and MSB: 12801cd85963SJason M. Bills *data_len += 12811cd85963SJason M. Bills sizeof(resp->next_record_id_lsb) + sizeof(resp->next_record_id_msb); 1282bbef71c2SEmily Shaffer 1283bbef71c2SEmily Shaffer return ret; 1284bbef71c2SEmily Shaffer } 1285bbef71c2SEmily Shaffer 12863342a8e0SJia, Chunhui static bool isFromSystemChannel() 12873342a8e0SJia, Chunhui { 12883342a8e0SJia, Chunhui // TODO we could not figure out where the request is from based on IPMI 12893342a8e0SJia, Chunhui // command handler parameters. because of it, we can not differentiate 12903342a8e0SJia, Chunhui // request from SMS/SMM or IPMB channel 12913342a8e0SJia, Chunhui return true; 12923342a8e0SJia, Chunhui } 12933342a8e0SJia, Chunhui 12943342a8e0SJia, Chunhui ipmi_ret_t ipmicmdPlatformEvent(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 12953342a8e0SJia, Chunhui ipmi_request_t request, 12963342a8e0SJia, Chunhui ipmi_response_t response, 12973342a8e0SJia, Chunhui ipmi_data_len_t dataLen, ipmi_context_t context) 12983342a8e0SJia, Chunhui { 12993342a8e0SJia, Chunhui uint16_t generatorID; 13003342a8e0SJia, Chunhui size_t count; 13013342a8e0SJia, Chunhui bool assert = true; 13023342a8e0SJia, Chunhui std::string sensorPath; 13033342a8e0SJia, Chunhui size_t paraLen = *dataLen; 13043342a8e0SJia, Chunhui PlatformEventRequest* req; 13053342a8e0SJia, Chunhui *dataLen = 0; 13063342a8e0SJia, Chunhui 13073342a8e0SJia, Chunhui if ((paraLen < selSystemEventSizeWith1Bytes) || 13083342a8e0SJia, Chunhui (paraLen > selSystemEventSizeWith3Bytes)) 13093342a8e0SJia, Chunhui { 13103342a8e0SJia, Chunhui return IPMI_CC_REQ_DATA_LEN_INVALID; 13113342a8e0SJia, Chunhui } 13123342a8e0SJia, Chunhui 13133342a8e0SJia, Chunhui if (isFromSystemChannel()) 13143342a8e0SJia, Chunhui { // first byte for SYSTEM Interface is Generator ID 13153342a8e0SJia, Chunhui // +1 to get common struct 13163342a8e0SJia, Chunhui req = reinterpret_cast<PlatformEventRequest*>((uint8_t*)request + 1); 13173342a8e0SJia, Chunhui // Capture the generator ID 13183342a8e0SJia, Chunhui generatorID = *reinterpret_cast<uint8_t*>(request); 13193342a8e0SJia, Chunhui // Platform Event usually comes from other firmware, like BIOS. 13203342a8e0SJia, Chunhui // Unlike BMC sensor, it does not have BMC DBUS sensor path. 13213342a8e0SJia, Chunhui sensorPath = "System"; 13223342a8e0SJia, Chunhui } 13233342a8e0SJia, Chunhui else 13243342a8e0SJia, Chunhui { 13253342a8e0SJia, Chunhui req = reinterpret_cast<PlatformEventRequest*>(request); 13263342a8e0SJia, Chunhui // TODO GenratorID for IPMB is combination of RqSA and RqLUN 13273342a8e0SJia, Chunhui generatorID = 0xff; 13283342a8e0SJia, Chunhui sensorPath = "IPMB"; 13293342a8e0SJia, Chunhui } 13303342a8e0SJia, Chunhui // Content of event data field depends on sensor class. 13313342a8e0SJia, Chunhui // When data0 bit[5:4] is non-zero, valid data counts is 3. 13323342a8e0SJia, Chunhui // When data0 bit[7:6] is non-zero, valid data counts is 2. 13333342a8e0SJia, Chunhui if (((req->data[0] & byte3EnableMask) != 0 && 13343342a8e0SJia, Chunhui paraLen < selSystemEventSizeWith3Bytes) || 13353342a8e0SJia, Chunhui ((req->data[0] & byte2EnableMask) != 0 && 13363342a8e0SJia, Chunhui paraLen < selSystemEventSizeWith2Bytes)) 13373342a8e0SJia, Chunhui { 13383342a8e0SJia, Chunhui return IPMI_CC_REQ_DATA_LEN_INVALID; 13393342a8e0SJia, Chunhui } 13403342a8e0SJia, Chunhui 13413342a8e0SJia, Chunhui // Count bytes of Event Data 13423342a8e0SJia, Chunhui if ((req->data[0] & byte3EnableMask) != 0) 13433342a8e0SJia, Chunhui { 13443342a8e0SJia, Chunhui count = 3; 13453342a8e0SJia, Chunhui } 13463342a8e0SJia, Chunhui else if ((req->data[0] & byte2EnableMask) != 0) 13473342a8e0SJia, Chunhui { 13483342a8e0SJia, Chunhui count = 2; 13493342a8e0SJia, Chunhui } 13503342a8e0SJia, Chunhui else 13513342a8e0SJia, Chunhui { 13523342a8e0SJia, Chunhui count = 1; 13533342a8e0SJia, Chunhui } 13543342a8e0SJia, Chunhui assert = req->eventDirectionType & directionMask ? false : true; 13553342a8e0SJia, Chunhui std::vector<uint8_t> eventData(req->data, req->data + count); 13563342a8e0SJia, Chunhui 13573342a8e0SJia, Chunhui sdbusplus::bus::bus dbus(bus); 13583342a8e0SJia, Chunhui std::string service = 13593342a8e0SJia, Chunhui ipmi::getService(dbus, ipmiSELAddInterface, ipmiSELPath); 13603342a8e0SJia, Chunhui sdbusplus::message::message writeSEL = dbus.new_method_call( 13613342a8e0SJia, Chunhui service.c_str(), ipmiSELPath, ipmiSELAddInterface, "IpmiSelAdd"); 13623342a8e0SJia, Chunhui writeSEL.append(ipmiSELAddMessage, sensorPath, eventData, assert, 13633342a8e0SJia, Chunhui generatorID); 13643342a8e0SJia, Chunhui try 13653342a8e0SJia, Chunhui { 13663342a8e0SJia, Chunhui dbus.call(writeSEL); 13673342a8e0SJia, Chunhui } 1368a2ad2da8SPatrick Williams catch (const sdbusplus::exception_t& e) 13693342a8e0SJia, Chunhui { 13703342a8e0SJia, Chunhui phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 13713342a8e0SJia, Chunhui return IPMI_CC_UNSPECIFIED_ERROR; 13723342a8e0SJia, Chunhui } 13733342a8e0SJia, Chunhui return IPMI_CC_OK; 13743342a8e0SJia, Chunhui } 13753342a8e0SJia, Chunhui 137698a23840SMatthew Barth void register_netfn_sen_functions() 137798a23840SMatthew Barth { 1378d351a729SWilly Tu // Handlers with dbus-sdr handler implementation. 1379d351a729SWilly Tu // Do not register the hander if it dynamic sensors stack is used. 1380a8be7dc8SDeepak Kumar Sahu 1381d351a729SWilly Tu #ifndef FEATURE_DYNAMIC_SENSORS 1382be5c6b2aSLei YU 1383962e68baSLei YU #ifdef FEATURE_SENSORS_CACHE 1384be5c6b2aSLei YU // Initialize the sensor matches 1385be5c6b2aSLei YU initSensorMatches(); 1386962e68baSLei YU #endif 1387be5c6b2aSLei YU 13880573237fSTom // <Set Sensor Reading and Event Status> 13899da3a750SDeepak Kumar Sahu ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor, 13909da3a750SDeepak Kumar Sahu ipmi::sensor_event::cmdSetSensorReadingAndEvtSts, 13919da3a750SDeepak Kumar Sahu ipmi::Privilege::Operator, ipmiSetSensorReading); 13920573237fSTom // <Get Sensor Reading> 13934c3feba5Sjayaprakash Mutyala ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor, 13944c3feba5Sjayaprakash Mutyala ipmi::sensor_event::cmdGetSensorReading, 13954c3feba5Sjayaprakash Mutyala ipmi::Privilege::User, ipmiSensorGetSensorReading); 1396a344afc0SEmily Shaffer 13975ca50959STom Joseph // <Reserve Device SDR Repository> 1398d957823eSjayaprakash Mutyala ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor, 1399d957823eSjayaprakash Mutyala ipmi::sensor_event::cmdReserveDeviceSdrRepository, 1400d957823eSjayaprakash Mutyala ipmi::Privilege::User, ipmiSensorReserveSdr); 140198a23840SMatthew Barth 14025ca50959STom Joseph // <Get Device SDR Info> 1403d957823eSjayaprakash Mutyala ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor, 1404d957823eSjayaprakash Mutyala ipmi::sensor_event::cmdGetDeviceSdrInfo, 1405d957823eSjayaprakash Mutyala ipmi::Privilege::User, ipmiSensorGetDeviceSdrInfo); 1406bbef71c2SEmily Shaffer 14075c0beec1SDhruvaraj Subhashchandran // <Get Sensor Thresholds> 1408996c9798Sjayaprakash Mutyala ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor, 1409996c9798Sjayaprakash Mutyala ipmi::sensor_event::cmdGetSensorThreshold, 1410996c9798Sjayaprakash Mutyala ipmi::Privilege::User, ipmiSensorGetSensorThresholds); 14115c0beec1SDhruvaraj Subhashchandran 1412f93da667SLotus Xu // <Set Sensor Thresholds> 1413f93da667SLotus Xu ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor, 1414f93da667SLotus Xu ipmi::sensor_event::cmdSetSensorThreshold, 1415f93da667SLotus Xu ipmi::Privilege::User, ipmiSenSetSensorThresholds); 1416d351a729SWilly Tu #endif 1417d351a729SWilly Tu 1418d351a729SWilly Tu // Common Handers used by both implementation. 1419d351a729SWilly Tu 1420d351a729SWilly Tu // <Platform Event Message> 1421d351a729SWilly Tu ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_PLATFORM_EVENT, nullptr, 1422d351a729SWilly Tu ipmicmdPlatformEvent, PRIVILEGE_OPERATOR); 1423d351a729SWilly Tu 1424d351a729SWilly Tu // <Get Sensor Type> 1425d351a729SWilly Tu ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnSensor, 1426d351a729SWilly Tu ipmi::sensor_event::cmdGetSensorType, 1427d351a729SWilly Tu ipmi::Privilege::User, ipmiGetSensorType); 1428d351a729SWilly Tu 1429d351a729SWilly Tu // <Get Device SDR> 1430d351a729SWilly Tu ipmi_register_callback(NETFUN_SENSOR, IPMI_CMD_GET_DEVICE_SDR, nullptr, 1431d351a729SWilly Tu ipmi_sen_get_sdr, PRIVILEGE_USER); 143298a23840SMatthew Barth return; 143398a23840SMatthew Barth } 1434