| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1 | #include "config.h" | 
 | 2 |  | 
| Tom Joseph | be5eaa1 | 2017-07-12 19:54:44 +0530 | [diff] [blame] | 3 | #include "dcmihandler.hpp" | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 4 |  | 
 | 5 | #include "net.hpp" | 
 | 6 | #include "utils.hpp" | 
 | 7 |  | 
| Patrick Venture | 46470a3 | 2018-09-07 19:26:25 -0700 | [diff] [blame] | 8 | #include <host-ipmid/ipmid-api.h> | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 9 |  | 
 | 10 | #include <bitset> | 
 | 11 | #include <cmath> | 
 | 12 | #include <fstream> | 
 | 13 | #include <nlohmann/json.hpp> | 
| Tom Joseph | be5eaa1 | 2017-07-12 19:54:44 +0530 | [diff] [blame] | 14 | #include <phosphor-logging/elog-errors.hpp> | 
| Andrew Geissler | 50c0c8f | 2017-07-11 16:18:51 -0500 | [diff] [blame] | 15 | #include <phosphor-logging/log.hpp> | 
 | 16 | #include <sdbusplus/bus.hpp> | 
| William A. Kennington III | 4c00802 | 2018-10-12 17:18:14 -0700 | [diff] [blame] | 17 | #include <sdbusplus/message/types.hpp> | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 18 | #include <xyz/openbmc_project/Common/error.hpp> | 
 | 19 |  | 
| Tom Joseph | be5eaa1 | 2017-07-12 19:54:44 +0530 | [diff] [blame] | 20 | using namespace phosphor::logging; | 
 | 21 | using InternalFailure = | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 22 |     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; | 
| Chris Austen | 1810bec | 2015-10-13 12:12:39 -0500 | [diff] [blame] | 23 |  | 
 | 24 | void register_netfn_dcmi_functions() __attribute__((constructor)); | 
 | 25 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 26 | constexpr auto PCAP_PATH = "/xyz/openbmc_project/control/host0/power_cap"; | 
| Andrew Geissler | 50c0c8f | 2017-07-11 16:18:51 -0500 | [diff] [blame] | 27 | constexpr auto PCAP_INTERFACE = "xyz.openbmc_project.Control.Power.Cap"; | 
 | 28 |  | 
 | 29 | constexpr auto POWER_CAP_PROP = "PowerCap"; | 
 | 30 | constexpr auto POWER_CAP_ENABLE_PROP = "PowerCapEnable"; | 
 | 31 |  | 
| Dhruvaraj Subhashchandran | e29be41 | 2018-01-16 05:11:56 -0600 | [diff] [blame] | 32 | constexpr auto DCMI_PARAMETER_REVISION = 2; | 
 | 33 | constexpr auto DCMI_SPEC_MAJOR_VERSION = 1; | 
 | 34 | constexpr auto DCMI_SPEC_MINOR_VERSION = 5; | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 35 | constexpr auto DCMI_CONFIG_PARAMETER_REVISION = 1; | 
 | 36 | constexpr auto DCMI_RAND_BACK_OFF_MASK = 0x80; | 
 | 37 | constexpr auto DCMI_OPTION_60_43_MASK = 0x02; | 
 | 38 | constexpr auto DCMI_OPTION_12_MASK = 0x01; | 
 | 39 | constexpr auto DCMI_ACTIVATE_DHCP_MASK = 0x01; | 
 | 40 | constexpr auto DCMI_ACTIVATE_DHCP_REPLY = 0x00; | 
 | 41 | constexpr auto DCMI_SET_CONF_PARAM_REQ_PACKET_MAX_SIZE = 0x05; | 
 | 42 | constexpr auto DCMI_SET_CONF_PARAM_REQ_PACKET_MIN_SIZE = 0x04; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 43 | constexpr auto DHCP_TIMING1 = 0x04;       // 4 sec | 
 | 44 | constexpr auto DHCP_TIMING2_UPPER = 0x00; // 2 min | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 45 | constexpr auto DHCP_TIMING2_LOWER = 0x78; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 46 | constexpr auto DHCP_TIMING3_UPPER = 0x00; // 64 sec | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 47 | constexpr auto DHCP_TIMING3_LOWER = 0x40; | 
 | 48 | // When DHCP Option 12 is enabled the string "SendHostName=true" will be | 
 | 49 | // added into n/w configuration file and the parameter | 
 | 50 | // SendHostNameEnabled will set to true. | 
 | 51 | constexpr auto DHCP_OPT12_ENABLED = "SendHostNameEnabled"; | 
 | 52 |  | 
| Dhruvaraj Subhashchandran | e29be41 | 2018-01-16 05:11:56 -0600 | [diff] [blame] | 53 | constexpr auto DCMI_CAP_JSON_FILE = "/usr/share/ipmi-providers/dcmi_cap.json"; | 
 | 54 |  | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 55 | constexpr auto SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value"; | 
 | 56 | constexpr auto SENSOR_VALUE_PROP = "Value"; | 
 | 57 | constexpr auto SENSOR_SCALE_PROP = "Scale"; | 
 | 58 |  | 
| Andrew Geissler | 50c0c8f | 2017-07-11 16:18:51 -0500 | [diff] [blame] | 59 | using namespace phosphor::logging; | 
| William A. Kennington III | 4c00802 | 2018-10-12 17:18:14 -0700 | [diff] [blame] | 60 | namespace variant_ns = sdbusplus::message::variant_ns; | 
| Andrew Geissler | 50c0c8f | 2017-07-11 16:18:51 -0500 | [diff] [blame] | 61 |  | 
| Tom Joseph | b9d86f4 | 2017-07-26 18:03:47 +0530 | [diff] [blame] | 62 | namespace dcmi | 
 | 63 | { | 
 | 64 |  | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 65 | // Refer Table 6-14, DCMI Entity ID Extension, DCMI v1.5 spec | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 66 | static const std::map<uint8_t, std::string> entityIdToName{ | 
 | 67 |     {0x40, "inlet"}, {0x37, "inlet"},     {0x41, "cpu"}, | 
 | 68 |     {0x03, "cpu"},   {0x42, "baseboard"}, {0x07, "baseboard"}}; | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 69 |  | 
| Andrew Geissler | 50c0c8f | 2017-07-11 16:18:51 -0500 | [diff] [blame] | 70 | uint32_t getPcap(sdbusplus::bus::bus& bus) | 
 | 71 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 72 |     auto settingService = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH); | 
| Andrew Geissler | 50c0c8f | 2017-07-11 16:18:51 -0500 | [diff] [blame] | 73 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 74 |     auto method = bus.new_method_call(settingService.c_str(), PCAP_PATH, | 
 | 75 |                                       "org.freedesktop.DBus.Properties", "Get"); | 
| Andrew Geissler | 50c0c8f | 2017-07-11 16:18:51 -0500 | [diff] [blame] | 76 |  | 
 | 77 |     method.append(PCAP_INTERFACE, POWER_CAP_PROP); | 
 | 78 |     auto reply = bus.call(method); | 
 | 79 |  | 
 | 80 |     if (reply.is_method_error()) | 
 | 81 |     { | 
 | 82 |         log<level::ERR>("Error in getPcap prop"); | 
| Tom Joseph | b9d86f4 | 2017-07-26 18:03:47 +0530 | [diff] [blame] | 83 |         elog<InternalFailure>(); | 
| Andrew Geissler | 50c0c8f | 2017-07-11 16:18:51 -0500 | [diff] [blame] | 84 |     } | 
 | 85 |     sdbusplus::message::variant<uint32_t> pcap; | 
 | 86 |     reply.read(pcap); | 
 | 87 |  | 
| William A. Kennington III | 4c00802 | 2018-10-12 17:18:14 -0700 | [diff] [blame] | 88 |     return variant_ns::get<uint32_t>(pcap); | 
| Andrew Geissler | 50c0c8f | 2017-07-11 16:18:51 -0500 | [diff] [blame] | 89 | } | 
 | 90 |  | 
 | 91 | bool getPcapEnabled(sdbusplus::bus::bus& bus) | 
 | 92 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 93 |     auto settingService = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH); | 
| Andrew Geissler | 50c0c8f | 2017-07-11 16:18:51 -0500 | [diff] [blame] | 94 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 95 |     auto method = bus.new_method_call(settingService.c_str(), PCAP_PATH, | 
 | 96 |                                       "org.freedesktop.DBus.Properties", "Get"); | 
| Andrew Geissler | 50c0c8f | 2017-07-11 16:18:51 -0500 | [diff] [blame] | 97 |  | 
 | 98 |     method.append(PCAP_INTERFACE, POWER_CAP_ENABLE_PROP); | 
 | 99 |     auto reply = bus.call(method); | 
 | 100 |  | 
 | 101 |     if (reply.is_method_error()) | 
 | 102 |     { | 
 | 103 |         log<level::ERR>("Error in getPcapEnabled prop"); | 
| Tom Joseph | b9d86f4 | 2017-07-26 18:03:47 +0530 | [diff] [blame] | 104 |         elog<InternalFailure>(); | 
| Andrew Geissler | 50c0c8f | 2017-07-11 16:18:51 -0500 | [diff] [blame] | 105 |     } | 
 | 106 |     sdbusplus::message::variant<bool> pcapEnabled; | 
 | 107 |     reply.read(pcapEnabled); | 
 | 108 |  | 
| William A. Kennington III | 4c00802 | 2018-10-12 17:18:14 -0700 | [diff] [blame] | 109 |     return variant_ns::get<bool>(pcapEnabled); | 
| Andrew Geissler | 50c0c8f | 2017-07-11 16:18:51 -0500 | [diff] [blame] | 110 | } | 
| Chris Austen | 1810bec | 2015-10-13 12:12:39 -0500 | [diff] [blame] | 111 |  | 
| Tom Joseph | 46fa37d | 2017-07-26 18:11:55 +0530 | [diff] [blame] | 112 | void setPcap(sdbusplus::bus::bus& bus, const uint32_t powerCap) | 
 | 113 | { | 
 | 114 |     auto service = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH); | 
 | 115 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 116 |     auto method = bus.new_method_call(service.c_str(), PCAP_PATH, | 
 | 117 |                                       "org.freedesktop.DBus.Properties", "Set"); | 
| Tom Joseph | 46fa37d | 2017-07-26 18:11:55 +0530 | [diff] [blame] | 118 |  | 
 | 119 |     method.append(PCAP_INTERFACE, POWER_CAP_PROP); | 
 | 120 |     method.append(sdbusplus::message::variant<uint32_t>(powerCap)); | 
 | 121 |  | 
 | 122 |     auto reply = bus.call(method); | 
 | 123 |  | 
 | 124 |     if (reply.is_method_error()) | 
 | 125 |     { | 
 | 126 |         log<level::ERR>("Error in setPcap property"); | 
 | 127 |         elog<InternalFailure>(); | 
 | 128 |     } | 
 | 129 | } | 
 | 130 |  | 
| Tom Joseph | 6c8d51b | 2017-07-26 18:18:06 +0530 | [diff] [blame] | 131 | void setPcapEnable(sdbusplus::bus::bus& bus, bool enabled) | 
 | 132 | { | 
 | 133 |     auto service = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH); | 
 | 134 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 135 |     auto method = bus.new_method_call(service.c_str(), PCAP_PATH, | 
 | 136 |                                       "org.freedesktop.DBus.Properties", "Set"); | 
| Tom Joseph | 6c8d51b | 2017-07-26 18:18:06 +0530 | [diff] [blame] | 137 |  | 
 | 138 |     method.append(PCAP_INTERFACE, POWER_CAP_ENABLE_PROP); | 
 | 139 |     method.append(sdbusplus::message::variant<bool>(enabled)); | 
 | 140 |  | 
 | 141 |     auto reply = bus.call(method); | 
 | 142 |  | 
 | 143 |     if (reply.is_method_error()) | 
 | 144 |     { | 
 | 145 |         log<level::ERR>("Error in setPcapEnabled property"); | 
 | 146 |         elog<InternalFailure>(); | 
 | 147 |     } | 
 | 148 | } | 
 | 149 |  | 
| Tom Joseph | be5eaa1 | 2017-07-12 19:54:44 +0530 | [diff] [blame] | 150 | void readAssetTagObjectTree(dcmi::assettag::ObjectTree& objectTree) | 
 | 151 | { | 
 | 152 |     static constexpr auto mapperBusName = "xyz.openbmc_project.ObjectMapper"; | 
 | 153 |     static constexpr auto mapperObjPath = "/xyz/openbmc_project/object_mapper"; | 
 | 154 |     static constexpr auto mapperIface = "xyz.openbmc_project.ObjectMapper"; | 
 | 155 |     static constexpr auto inventoryRoot = "/xyz/openbmc_project/inventory/"; | 
 | 156 |  | 
 | 157 |     sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; | 
 | 158 |     auto depth = 0; | 
 | 159 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 160 |     auto mapperCall = bus.new_method_call(mapperBusName, mapperObjPath, | 
 | 161 |                                           mapperIface, "GetSubTree"); | 
| Tom Joseph | be5eaa1 | 2017-07-12 19:54:44 +0530 | [diff] [blame] | 162 |  | 
 | 163 |     mapperCall.append(inventoryRoot); | 
 | 164 |     mapperCall.append(depth); | 
 | 165 |     mapperCall.append(std::vector<std::string>({dcmi::assetTagIntf})); | 
 | 166 |  | 
 | 167 |     auto mapperReply = bus.call(mapperCall); | 
 | 168 |     if (mapperReply.is_method_error()) | 
 | 169 |     { | 
 | 170 |         log<level::ERR>("Error in mapper call"); | 
 | 171 |         elog<InternalFailure>(); | 
 | 172 |     } | 
 | 173 |  | 
 | 174 |     mapperReply.read(objectTree); | 
 | 175 |  | 
 | 176 |     if (objectTree.empty()) | 
 | 177 |     { | 
 | 178 |         log<level::ERR>("AssetTag property is not populated"); | 
 | 179 |         elog<InternalFailure>(); | 
 | 180 |     } | 
 | 181 | } | 
 | 182 |  | 
 | 183 | std::string readAssetTag() | 
 | 184 | { | 
 | 185 |     sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; | 
 | 186 |     dcmi::assettag::ObjectTree objectTree; | 
 | 187 |  | 
 | 188 |     // Read the object tree with the inventory root to figure out the object | 
 | 189 |     // that has implemented the Asset tag interface. | 
 | 190 |     readAssetTagObjectTree(objectTree); | 
 | 191 |  | 
 | 192 |     auto method = bus.new_method_call( | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 193 |         (objectTree.begin()->second.begin()->first).c_str(), | 
 | 194 |         (objectTree.begin()->first).c_str(), dcmi::propIntf, "Get"); | 
| Tom Joseph | be5eaa1 | 2017-07-12 19:54:44 +0530 | [diff] [blame] | 195 |     method.append(dcmi::assetTagIntf); | 
 | 196 |     method.append(dcmi::assetTagProp); | 
 | 197 |  | 
 | 198 |     auto reply = bus.call(method); | 
 | 199 |     if (reply.is_method_error()) | 
 | 200 |     { | 
 | 201 |         log<level::ERR>("Error in reading asset tag"); | 
 | 202 |         elog<InternalFailure>(); | 
 | 203 |     } | 
 | 204 |  | 
 | 205 |     sdbusplus::message::variant<std::string> assetTag; | 
 | 206 |     reply.read(assetTag); | 
 | 207 |  | 
| William A. Kennington III | 4c00802 | 2018-10-12 17:18:14 -0700 | [diff] [blame] | 208 |     return variant_ns::get<std::string>(assetTag); | 
| Tom Joseph | be5eaa1 | 2017-07-12 19:54:44 +0530 | [diff] [blame] | 209 | } | 
 | 210 |  | 
| Tom Joseph | be5b989 | 2017-07-15 00:55:23 +0530 | [diff] [blame] | 211 | void writeAssetTag(const std::string& assetTag) | 
 | 212 | { | 
 | 213 |     sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; | 
 | 214 |     dcmi::assettag::ObjectTree objectTree; | 
 | 215 |  | 
 | 216 |     // Read the object tree with the inventory root to figure out the object | 
 | 217 |     // that has implemented the Asset tag interface. | 
 | 218 |     readAssetTagObjectTree(objectTree); | 
 | 219 |  | 
 | 220 |     auto method = bus.new_method_call( | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 221 |         (objectTree.begin()->second.begin()->first).c_str(), | 
 | 222 |         (objectTree.begin()->first).c_str(), dcmi::propIntf, "Set"); | 
| Tom Joseph | be5b989 | 2017-07-15 00:55:23 +0530 | [diff] [blame] | 223 |     method.append(dcmi::assetTagIntf); | 
 | 224 |     method.append(dcmi::assetTagProp); | 
 | 225 |     method.append(sdbusplus::message::variant<std::string>(assetTag)); | 
 | 226 |  | 
 | 227 |     auto reply = bus.call(method); | 
 | 228 |     if (reply.is_method_error()) | 
 | 229 |     { | 
 | 230 |         log<level::ERR>("Error in writing asset tag"); | 
 | 231 |         elog<InternalFailure>(); | 
 | 232 |     } | 
 | 233 | } | 
 | 234 |  | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 235 | std::string getHostName(void) | 
 | 236 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 237 |     sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 238 |  | 
 | 239 |     auto service = ipmi::getService(bus, networkConfigIntf, networkConfigObj); | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 240 |     auto value = ipmi::getDbusProperty(bus, service, networkConfigObj, | 
 | 241 |                                        networkConfigIntf, hostNameProp); | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 242 |  | 
| William A. Kennington III | 4c00802 | 2018-10-12 17:18:14 -0700 | [diff] [blame] | 243 |     return variant_ns::get<std::string>(value); | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 244 | } | 
 | 245 |  | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 246 | bool getDHCPEnabled() | 
 | 247 | { | 
 | 248 |     sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; | 
 | 249 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 250 |     auto ethdevice = | 
 | 251 |         ipmi::network::ChanneltoEthernet(ethernetDefaultChannelNum); | 
 | 252 |     auto ethernetObj = | 
 | 253 |         ipmi::getDbusObject(bus, ethernetIntf, networkRoot, ethdevice); | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 254 |     auto service = ipmi::getService(bus, ethernetIntf, ethernetObj.first); | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 255 |     auto value = ipmi::getDbusProperty(bus, service, ethernetObj.first, | 
 | 256 |                                        ethernetIntf, "DHCPEnabled"); | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 257 |  | 
| William A. Kennington III | 4c00802 | 2018-10-12 17:18:14 -0700 | [diff] [blame] | 258 |     return variant_ns::get<bool>(value); | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 259 | } | 
 | 260 |  | 
 | 261 | bool getDHCPOption(std::string prop) | 
 | 262 | { | 
 | 263 |     sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; | 
 | 264 |  | 
 | 265 |     auto service = ipmi::getService(bus, dhcpIntf, dhcpObj); | 
 | 266 |     auto value = ipmi::getDbusProperty(bus, service, dhcpObj, dhcpIntf, prop); | 
 | 267 |  | 
| William A. Kennington III | 4c00802 | 2018-10-12 17:18:14 -0700 | [diff] [blame] | 268 |     return variant_ns::get<bool>(value); | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 269 | } | 
 | 270 |  | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 271 | void setDHCPOption(std::string prop, bool value) | 
 | 272 | { | 
 | 273 |     sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; | 
 | 274 |  | 
 | 275 |     auto service = ipmi::getService(bus, dhcpIntf, dhcpObj); | 
 | 276 |     ipmi::setDbusProperty(bus, service, dhcpObj, dhcpIntf, prop, value); | 
 | 277 | } | 
 | 278 |  | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 279 | Json parseSensorConfig() | 
 | 280 | { | 
 | 281 |     std::ifstream jsonFile(configFile); | 
 | 282 |     if (!jsonFile.is_open()) | 
 | 283 |     { | 
 | 284 |         log<level::ERR>("Temperature readings JSON file not found"); | 
 | 285 |         elog<InternalFailure>(); | 
 | 286 |     } | 
 | 287 |  | 
 | 288 |     auto data = Json::parse(jsonFile, nullptr, false); | 
 | 289 |     if (data.is_discarded()) | 
 | 290 |     { | 
 | 291 |         log<level::ERR>("Temperature readings JSON parser failure"); | 
 | 292 |         elog<InternalFailure>(); | 
 | 293 |     } | 
 | 294 |  | 
 | 295 |     return data; | 
 | 296 | } | 
 | 297 |  | 
| Tom Joseph | be5eaa1 | 2017-07-12 19:54:44 +0530 | [diff] [blame] | 298 | } // namespace dcmi | 
| Chris Austen | 1810bec | 2015-10-13 12:12:39 -0500 | [diff] [blame] | 299 |  | 
| Tom Joseph | b9d86f4 | 2017-07-26 18:03:47 +0530 | [diff] [blame] | 300 | ipmi_ret_t getPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
 | 301 |                          ipmi_request_t request, ipmi_response_t response, | 
 | 302 |                          ipmi_data_len_t data_len, ipmi_context_t context) | 
 | 303 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 304 |     auto requestData = | 
 | 305 |         reinterpret_cast<const dcmi::GetPowerLimitRequest*>(request); | 
| Tom Joseph | b9d86f4 | 2017-07-26 18:03:47 +0530 | [diff] [blame] | 306 |     std::vector<uint8_t> outPayload(sizeof(dcmi::GetPowerLimitResponse)); | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 307 |     auto responseData = | 
 | 308 |         reinterpret_cast<dcmi::GetPowerLimitResponse*>(outPayload.data()); | 
| Tom Joseph | b9d86f4 | 2017-07-26 18:03:47 +0530 | [diff] [blame] | 309 |  | 
 | 310 |     if (requestData->groupID != dcmi::groupExtId) | 
 | 311 |     { | 
 | 312 |         *data_len = 0; | 
 | 313 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 314 |     } | 
 | 315 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 316 |     sdbusplus::bus::bus sdbus{ipmid_get_sd_bus_connection()}; | 
| Tom Joseph | b9d86f4 | 2017-07-26 18:03:47 +0530 | [diff] [blame] | 317 |     uint32_t pcapValue = 0; | 
 | 318 |     bool pcapEnable = false; | 
 | 319 |  | 
 | 320 |     try | 
 | 321 |     { | 
 | 322 |         pcapValue = dcmi::getPcap(sdbus); | 
 | 323 |         pcapEnable = dcmi::getPcapEnabled(sdbus); | 
 | 324 |     } | 
 | 325 |     catch (InternalFailure& e) | 
 | 326 |     { | 
 | 327 |         *data_len = 0; | 
 | 328 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 329 |     } | 
 | 330 |  | 
 | 331 |     responseData->groupID = dcmi::groupExtId; | 
 | 332 |  | 
 | 333 |     /* | 
 | 334 |      * Exception action if power limit is exceeded and cannot be controlled | 
 | 335 |      * with the correction time limit is hardcoded to Hard Power Off system | 
 | 336 |      * and log event to SEL. | 
 | 337 |      */ | 
 | 338 |     constexpr auto exception = 0x01; | 
 | 339 |     responseData->exceptionAction = exception; | 
 | 340 |  | 
 | 341 |     responseData->powerLimit = static_cast<uint16_t>(pcapValue); | 
 | 342 |  | 
 | 343 |     /* | 
 | 344 |      * Correction time limit and Statistics sampling period is currently not | 
 | 345 |      * populated. | 
 | 346 |      */ | 
 | 347 |  | 
 | 348 |     *data_len = outPayload.size(); | 
 | 349 |     memcpy(response, outPayload.data(), *data_len); | 
 | 350 |  | 
 | 351 |     if (pcapEnable) | 
 | 352 |     { | 
 | 353 |         return IPMI_CC_OK; | 
 | 354 |     } | 
 | 355 |     else | 
 | 356 |     { | 
 | 357 |         return IPMI_DCMI_CC_NO_ACTIVE_POWER_LIMIT; | 
 | 358 |     } | 
 | 359 | } | 
 | 360 |  | 
| Tom Joseph | 46fa37d | 2017-07-26 18:11:55 +0530 | [diff] [blame] | 361 | ipmi_ret_t setPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
 | 362 |                          ipmi_request_t request, ipmi_response_t response, | 
 | 363 |                          ipmi_data_len_t data_len, ipmi_context_t context) | 
 | 364 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 365 |     auto requestData = | 
 | 366 |         reinterpret_cast<const dcmi::SetPowerLimitRequest*>(request); | 
| Tom Joseph | 46fa37d | 2017-07-26 18:11:55 +0530 | [diff] [blame] | 367 |     std::vector<uint8_t> outPayload(sizeof(dcmi::SetPowerLimitResponse)); | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 368 |     auto responseData = | 
 | 369 |         reinterpret_cast<dcmi::SetPowerLimitResponse*>(outPayload.data()); | 
| Tom Joseph | 46fa37d | 2017-07-26 18:11:55 +0530 | [diff] [blame] | 370 |  | 
 | 371 |     if (requestData->groupID != dcmi::groupExtId) | 
 | 372 |     { | 
 | 373 |         *data_len = 0; | 
 | 374 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 375 |     } | 
 | 376 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 377 |     sdbusplus::bus::bus sdbus{ipmid_get_sd_bus_connection()}; | 
| Tom Joseph | 46fa37d | 2017-07-26 18:11:55 +0530 | [diff] [blame] | 378 |  | 
 | 379 |     // Only process the power limit requested in watts. | 
 | 380 |     try | 
 | 381 |     { | 
 | 382 |         dcmi::setPcap(sdbus, requestData->powerLimit); | 
 | 383 |     } | 
 | 384 |     catch (InternalFailure& e) | 
 | 385 |     { | 
 | 386 |         *data_len = 0; | 
 | 387 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 388 |     } | 
 | 389 |  | 
 | 390 |     log<level::INFO>("Set Power Cap", | 
 | 391 |                      entry("POWERCAP=%u", requestData->powerLimit)); | 
 | 392 |  | 
 | 393 |     responseData->groupID = dcmi::groupExtId; | 
 | 394 |     memcpy(response, outPayload.data(), outPayload.size()); | 
 | 395 |     *data_len = outPayload.size(); | 
 | 396 |  | 
 | 397 |     return IPMI_CC_OK; | 
 | 398 | } | 
 | 399 |  | 
| Tom Joseph | 6c8d51b | 2017-07-26 18:18:06 +0530 | [diff] [blame] | 400 | ipmi_ret_t applyPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
 | 401 |                            ipmi_request_t request, ipmi_response_t response, | 
 | 402 |                            ipmi_data_len_t data_len, ipmi_context_t context) | 
 | 403 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 404 |     auto requestData = | 
 | 405 |         reinterpret_cast<const dcmi::ApplyPowerLimitRequest*>(request); | 
| Tom Joseph | 6c8d51b | 2017-07-26 18:18:06 +0530 | [diff] [blame] | 406 |     std::vector<uint8_t> outPayload(sizeof(dcmi::ApplyPowerLimitResponse)); | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 407 |     auto responseData = | 
 | 408 |         reinterpret_cast<dcmi::ApplyPowerLimitResponse*>(outPayload.data()); | 
| Tom Joseph | 6c8d51b | 2017-07-26 18:18:06 +0530 | [diff] [blame] | 409 |  | 
 | 410 |     if (requestData->groupID != dcmi::groupExtId) | 
 | 411 |     { | 
 | 412 |         *data_len = 0; | 
 | 413 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 414 |     } | 
 | 415 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 416 |     sdbusplus::bus::bus sdbus{ipmid_get_sd_bus_connection()}; | 
| Tom Joseph | 6c8d51b | 2017-07-26 18:18:06 +0530 | [diff] [blame] | 417 |  | 
 | 418 |     try | 
 | 419 |     { | 
 | 420 |         dcmi::setPcapEnable(sdbus, | 
 | 421 |                             static_cast<bool>(requestData->powerLimitAction)); | 
 | 422 |     } | 
 | 423 |     catch (InternalFailure& e) | 
 | 424 |     { | 
 | 425 |         *data_len = 0; | 
 | 426 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 427 |     } | 
 | 428 |  | 
 | 429 |     log<level::INFO>("Set Power Cap Enable", | 
 | 430 |                      entry("POWERCAPENABLE=%u", requestData->powerLimitAction)); | 
 | 431 |  | 
 | 432 |     responseData->groupID = dcmi::groupExtId; | 
 | 433 |     memcpy(response, outPayload.data(), outPayload.size()); | 
 | 434 |     *data_len = outPayload.size(); | 
 | 435 |  | 
 | 436 |     return IPMI_CC_OK; | 
 | 437 | } | 
 | 438 |  | 
| Tom Joseph | 6f6dd4d | 2017-07-12 20:07:11 +0530 | [diff] [blame] | 439 | ipmi_ret_t getAssetTag(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
 | 440 |                        ipmi_request_t request, ipmi_response_t response, | 
 | 441 |                        ipmi_data_len_t data_len, ipmi_context_t context) | 
 | 442 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 443 |     auto requestData = | 
 | 444 |         reinterpret_cast<const dcmi::GetAssetTagRequest*>(request); | 
| Tom Joseph | 6f6dd4d | 2017-07-12 20:07:11 +0530 | [diff] [blame] | 445 |     std::vector<uint8_t> outPayload(sizeof(dcmi::GetAssetTagResponse)); | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 446 |     auto responseData = | 
 | 447 |         reinterpret_cast<dcmi::GetAssetTagResponse*>(outPayload.data()); | 
| Tom Joseph | 6f6dd4d | 2017-07-12 20:07:11 +0530 | [diff] [blame] | 448 |  | 
 | 449 |     if (requestData->groupID != dcmi::groupExtId) | 
 | 450 |     { | 
 | 451 |         *data_len = 0; | 
 | 452 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 453 |     } | 
 | 454 |  | 
 | 455 |     // Verify offset to read and number of bytes to read are not exceeding the | 
 | 456 |     // range. | 
 | 457 |     if ((requestData->offset > dcmi::assetTagMaxOffset) || | 
 | 458 |         (requestData->bytes > dcmi::maxBytes) || | 
 | 459 |         ((requestData->offset + requestData->bytes) > dcmi::assetTagMaxSize)) | 
 | 460 |     { | 
 | 461 |         *data_len = 0; | 
 | 462 |         return IPMI_CC_PARM_OUT_OF_RANGE; | 
 | 463 |     } | 
 | 464 |  | 
 | 465 |     std::string assetTag; | 
 | 466 |  | 
 | 467 |     try | 
 | 468 |     { | 
 | 469 |         assetTag = dcmi::readAssetTag(); | 
 | 470 |     } | 
 | 471 |     catch (InternalFailure& e) | 
 | 472 |     { | 
 | 473 |         *data_len = 0; | 
 | 474 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 475 |     } | 
 | 476 |  | 
 | 477 |     responseData->groupID = dcmi::groupExtId; | 
 | 478 |  | 
 | 479 |     // Return if the asset tag is not populated. | 
 | 480 |     if (!assetTag.size()) | 
 | 481 |     { | 
 | 482 |         responseData->tagLength = 0; | 
 | 483 |         memcpy(response, outPayload.data(), outPayload.size()); | 
 | 484 |         *data_len = outPayload.size(); | 
 | 485 |         return IPMI_CC_OK; | 
 | 486 |     } | 
 | 487 |  | 
 | 488 |     // If the asset tag is longer than 63 bytes, restrict it to 63 bytes to suit | 
 | 489 |     // Get Asset Tag command. | 
 | 490 |     if (assetTag.size() > dcmi::assetTagMaxSize) | 
 | 491 |     { | 
 | 492 |         assetTag.resize(dcmi::assetTagMaxSize); | 
 | 493 |     } | 
 | 494 |  | 
 | 495 |     // If the requested offset is beyond the asset tag size. | 
 | 496 |     if (requestData->offset >= assetTag.size()) | 
 | 497 |     { | 
 | 498 |         *data_len = 0; | 
 | 499 |         return IPMI_CC_PARM_OUT_OF_RANGE; | 
 | 500 |     } | 
 | 501 |  | 
 | 502 |     auto returnData = assetTag.substr(requestData->offset, requestData->bytes); | 
 | 503 |  | 
 | 504 |     responseData->tagLength = assetTag.size(); | 
 | 505 |  | 
 | 506 |     memcpy(response, outPayload.data(), outPayload.size()); | 
 | 507 |     memcpy(static_cast<uint8_t*>(response) + outPayload.size(), | 
 | 508 |            returnData.data(), returnData.size()); | 
 | 509 |     *data_len = outPayload.size() + returnData.size(); | 
 | 510 |  | 
 | 511 |     return IPMI_CC_OK; | 
 | 512 | } | 
 | 513 |  | 
| Tom Joseph | 545dd23 | 2017-07-12 20:20:49 +0530 | [diff] [blame] | 514 | ipmi_ret_t setAssetTag(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
 | 515 |                        ipmi_request_t request, ipmi_response_t response, | 
 | 516 |                        ipmi_data_len_t data_len, ipmi_context_t context) | 
 | 517 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 518 |     auto requestData = | 
 | 519 |         reinterpret_cast<const dcmi::SetAssetTagRequest*>(request); | 
| Tom Joseph | 545dd23 | 2017-07-12 20:20:49 +0530 | [diff] [blame] | 520 |     std::vector<uint8_t> outPayload(sizeof(dcmi::SetAssetTagResponse)); | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 521 |     auto responseData = | 
 | 522 |         reinterpret_cast<dcmi::SetAssetTagResponse*>(outPayload.data()); | 
| Tom Joseph | 545dd23 | 2017-07-12 20:20:49 +0530 | [diff] [blame] | 523 |  | 
 | 524 |     if (requestData->groupID != dcmi::groupExtId) | 
 | 525 |     { | 
 | 526 |         *data_len = 0; | 
 | 527 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 528 |     } | 
 | 529 |  | 
 | 530 |     // Verify offset to read and number of bytes to read are not exceeding the | 
 | 531 |     // range. | 
 | 532 |     if ((requestData->offset > dcmi::assetTagMaxOffset) || | 
 | 533 |         (requestData->bytes > dcmi::maxBytes) || | 
 | 534 |         ((requestData->offset + requestData->bytes) > dcmi::assetTagMaxSize)) | 
 | 535 |     { | 
 | 536 |         *data_len = 0; | 
 | 537 |         return IPMI_CC_PARM_OUT_OF_RANGE; | 
 | 538 |     } | 
 | 539 |  | 
 | 540 |     std::string assetTag; | 
 | 541 |  | 
 | 542 |     try | 
 | 543 |     { | 
 | 544 |         assetTag = dcmi::readAssetTag(); | 
 | 545 |  | 
 | 546 |         if (requestData->offset > assetTag.size()) | 
 | 547 |         { | 
 | 548 |             *data_len = 0; | 
 | 549 |             return IPMI_CC_PARM_OUT_OF_RANGE; | 
 | 550 |         } | 
 | 551 |  | 
 | 552 |         assetTag.replace(requestData->offset, | 
 | 553 |                          assetTag.size() - requestData->offset, | 
 | 554 |                          static_cast<const char*>(request) + | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 555 |                              sizeof(dcmi::SetAssetTagRequest), | 
| Tom Joseph | 545dd23 | 2017-07-12 20:20:49 +0530 | [diff] [blame] | 556 |                          requestData->bytes); | 
 | 557 |  | 
 | 558 |         dcmi::writeAssetTag(assetTag); | 
 | 559 |  | 
 | 560 |         responseData->groupID = dcmi::groupExtId; | 
 | 561 |         responseData->tagLength = assetTag.size(); | 
 | 562 |         memcpy(response, outPayload.data(), outPayload.size()); | 
 | 563 |         *data_len = outPayload.size(); | 
 | 564 |  | 
 | 565 |         return IPMI_CC_OK; | 
 | 566 |     } | 
 | 567 |     catch (InternalFailure& e) | 
 | 568 |     { | 
 | 569 |         *data_len = 0; | 
 | 570 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 571 |     } | 
 | 572 | } | 
 | 573 |  | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 574 | ipmi_ret_t getMgmntCtrlIdStr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 575 |                              ipmi_request_t request, ipmi_response_t response, | 
 | 576 |                              ipmi_data_len_t data_len, ipmi_context_t context) | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 577 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 578 |     auto requestData = | 
 | 579 |         reinterpret_cast<const dcmi::GetMgmntCtrlIdStrRequest*>(request); | 
 | 580 |     auto responseData = | 
 | 581 |         reinterpret_cast<dcmi::GetMgmntCtrlIdStrResponse*>(response); | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 582 |     std::string hostName; | 
 | 583 |  | 
 | 584 |     *data_len = 0; | 
 | 585 |  | 
 | 586 |     if (requestData->groupID != dcmi::groupExtId || | 
 | 587 |         requestData->bytes > dcmi::maxBytes || | 
 | 588 |         requestData->offset + requestData->bytes > dcmi::maxCtrlIdStrLen) | 
 | 589 |     { | 
 | 590 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 591 |     } | 
 | 592 |  | 
 | 593 |     try | 
 | 594 |     { | 
 | 595 |         hostName = dcmi::getHostName(); | 
 | 596 |     } | 
 | 597 |     catch (InternalFailure& e) | 
 | 598 |     { | 
 | 599 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 600 |     } | 
 | 601 |  | 
 | 602 |     if (requestData->offset > hostName.length()) | 
 | 603 |     { | 
 | 604 |         return IPMI_CC_PARM_OUT_OF_RANGE; | 
 | 605 |     } | 
 | 606 |     auto responseStr = hostName.substr(requestData->offset, requestData->bytes); | 
 | 607 |     auto responseStrLen = std::min(static_cast<std::size_t>(requestData->bytes), | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 608 |                                    responseStr.length() + 1); | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 609 |     responseData->groupID = dcmi::groupExtId; | 
 | 610 |     responseData->strLen = hostName.length(); | 
 | 611 |     std::copy(begin(responseStr), end(responseStr), responseData->data); | 
 | 612 |  | 
 | 613 |     *data_len = sizeof(*responseData) + responseStrLen; | 
 | 614 |     return IPMI_CC_OK; | 
 | 615 | } | 
 | 616 |  | 
 | 617 | ipmi_ret_t setMgmntCtrlIdStr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 618 |                              ipmi_request_t request, ipmi_response_t response, | 
 | 619 |                              ipmi_data_len_t data_len, ipmi_context_t context) | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 620 | { | 
 | 621 |     static std::array<char, dcmi::maxCtrlIdStrLen + 1> newCtrlIdStr; | 
 | 622 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 623 |     auto requestData = | 
 | 624 |         reinterpret_cast<const dcmi::SetMgmntCtrlIdStrRequest*>(request); | 
 | 625 |     auto responseData = | 
 | 626 |         reinterpret_cast<dcmi::SetMgmntCtrlIdStrResponse*>(response); | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 627 |  | 
 | 628 |     *data_len = 0; | 
 | 629 |  | 
 | 630 |     if (requestData->groupID != dcmi::groupExtId || | 
 | 631 |         requestData->bytes > dcmi::maxBytes || | 
 | 632 |         requestData->offset + requestData->bytes > dcmi::maxCtrlIdStrLen + 1 || | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 633 |         (requestData->offset + requestData->bytes == | 
 | 634 |              dcmi::maxCtrlIdStrLen + 1 && | 
 | 635 |          requestData->data[requestData->bytes - 1] != '\0')) | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 636 |     { | 
 | 637 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 638 |     } | 
 | 639 |  | 
 | 640 |     try | 
 | 641 |     { | 
 | 642 |         /* if there is no old value and offset is not 0 */ | 
 | 643 |         if (newCtrlIdStr[0] == '\0' && requestData->offset != 0) | 
 | 644 |         { | 
 | 645 |             /* read old ctrlIdStr */ | 
 | 646 |             auto hostName = dcmi::getHostName(); | 
 | 647 |             hostName.resize(dcmi::maxCtrlIdStrLen); | 
 | 648 |             std::copy(begin(hostName), end(hostName), begin(newCtrlIdStr)); | 
 | 649 |             newCtrlIdStr[hostName.length()] = '\0'; | 
 | 650 |         } | 
 | 651 |  | 
 | 652 |         /* replace part of string and mark byte after the last as \0 */ | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 653 |         auto restStrIter = | 
 | 654 |             std::copy_n(requestData->data, requestData->bytes, | 
 | 655 |                         begin(newCtrlIdStr) + requestData->offset); | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 656 |         /* if the last written byte is not 64th - add '\0' */ | 
 | 657 |         if (requestData->offset + requestData->bytes <= dcmi::maxCtrlIdStrLen) | 
 | 658 |         { | 
 | 659 |             *restStrIter = '\0'; | 
 | 660 |         } | 
 | 661 |  | 
 | 662 |         /* if input data contains '\0' whole string is sent - update hostname */ | 
 | 663 |         auto it = std::find(requestData->data, | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 664 |                             requestData->data + requestData->bytes, '\0'); | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 665 |         if (it != requestData->data + requestData->bytes) | 
 | 666 |         { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 667 |             sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 668 |             ipmi::setDbusProperty(bus, dcmi::networkServiceName, | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 669 |                                   dcmi::networkConfigObj, | 
 | 670 |                                   dcmi::networkConfigIntf, dcmi::hostNameProp, | 
 | 671 |                                   std::string(newCtrlIdStr.data())); | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 672 |         } | 
 | 673 |     } | 
 | 674 |     catch (InternalFailure& e) | 
 | 675 |     { | 
 | 676 |         *data_len = 0; | 
 | 677 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 678 |     } | 
 | 679 |  | 
 | 680 |     responseData->groupID = dcmi::groupExtId; | 
 | 681 |     responseData->offset = requestData->offset + requestData->bytes; | 
 | 682 |     *data_len = sizeof(*responseData); | 
 | 683 |     return IPMI_CC_OK; | 
 | 684 | } | 
 | 685 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 686 | // List of the capabilities under each parameter | 
 | 687 | dcmi::DCMICaps dcmiCaps = { | 
 | 688 |     // Supported DCMI Capabilities | 
 | 689 |     {dcmi::DCMICapParameters::SUPPORTED_DCMI_CAPS, | 
 | 690 |      {3, | 
 | 691 |       {{"PowerManagement", 2, 0, 1}, | 
 | 692 |        {"OOBSecondaryLan", 3, 2, 1}, | 
 | 693 |        {"SerialTMODE", 3, 1, 1}, | 
 | 694 |        {"InBandSystemInterfaceChannel", 3, 0, 1}}}}, | 
 | 695 |     // Mandatory Platform Attributes | 
 | 696 |     {dcmi::DCMICapParameters::MANDATORY_PLAT_ATTRIBUTES, | 
 | 697 |      {5, | 
 | 698 |       {{"SELAutoRollOver", 1, 15, 1}, | 
 | 699 |        {"FlushEntireSELUponRollOver", 1, 14, 1}, | 
 | 700 |        {"RecordLevelSELFlushUponRollOver", 1, 13, 1}, | 
 | 701 |        {"NumberOfSELEntries", 1, 0, 12}, | 
 | 702 |        {"TempMonitoringSamplingFreq", 5, 0, 8}}}}, | 
 | 703 |     // Optional Platform Attributes | 
 | 704 |     {dcmi::DCMICapParameters::OPTIONAL_PLAT_ATTRIBUTES, | 
 | 705 |      {2, | 
 | 706 |       {{"PowerMgmtDeviceSlaveAddress", 1, 1, 7}, | 
 | 707 |        {"BMCChannelNumber", 2, 4, 4}, | 
 | 708 |        {"DeviceRivision", 2, 0, 4}}}}, | 
 | 709 |     // Manageability Access Attributes | 
 | 710 |     {dcmi::DCMICapParameters::MANAGEABILITY_ACCESS_ATTRIBUTES, | 
 | 711 |      {3, | 
 | 712 |       {{"MandatoryPrimaryLanOOBSupport", 1, 0, 8}, | 
 | 713 |        {"OptionalSecondaryLanOOBSupport", 2, 0, 8}, | 
 | 714 |        {"OptionalSerialOOBMTMODECapability", 3, 0, 8}}}}}; | 
| Dhruvaraj Subhashchandran | e29be41 | 2018-01-16 05:11:56 -0600 | [diff] [blame] | 715 |  | 
 | 716 | ipmi_ret_t getDCMICapabilities(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
 | 717 |                                ipmi_request_t request, ipmi_response_t response, | 
 | 718 |                                ipmi_data_len_t data_len, ipmi_context_t context) | 
 | 719 | { | 
 | 720 |  | 
 | 721 |     std::ifstream dcmiCapFile(DCMI_CAP_JSON_FILE); | 
 | 722 |     if (!dcmiCapFile.is_open()) | 
 | 723 |     { | 
 | 724 |         log<level::ERR>("DCMI Capabilities file not found"); | 
 | 725 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 726 |     } | 
 | 727 |  | 
 | 728 |     auto data = nlohmann::json::parse(dcmiCapFile, nullptr, false); | 
 | 729 |     if (data.is_discarded()) | 
 | 730 |     { | 
 | 731 |         log<level::ERR>("DCMI Capabilities JSON parser failure"); | 
 | 732 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 733 |     } | 
 | 734 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 735 |     auto requestData = | 
 | 736 |         reinterpret_cast<const dcmi::GetDCMICapRequest*>(request); | 
| Dhruvaraj Subhashchandran | e29be41 | 2018-01-16 05:11:56 -0600 | [diff] [blame] | 737 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 738 |     // get list of capabilities in a parameter | 
| Dhruvaraj Subhashchandran | e29be41 | 2018-01-16 05:11:56 -0600 | [diff] [blame] | 739 |     auto caps = | 
 | 740 |         dcmiCaps.find(static_cast<dcmi::DCMICapParameters>(requestData->param)); | 
 | 741 |     if (caps == dcmiCaps.end()) | 
 | 742 |     { | 
 | 743 |         log<level::ERR>("Invalid input parameter"); | 
 | 744 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 745 |     } | 
 | 746 |  | 
 | 747 |     if (requestData->groupID != dcmi::groupExtId) | 
 | 748 |     { | 
 | 749 |         *data_len = 0; | 
 | 750 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 751 |     } | 
 | 752 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 753 |     auto responseData = reinterpret_cast<dcmi::GetDCMICapResponse*>(response); | 
| Dhruvaraj Subhashchandran | e29be41 | 2018-01-16 05:11:56 -0600 | [diff] [blame] | 754 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 755 |     // For each capabilities in a parameter fill the data from | 
 | 756 |     // the json file based on the capability name. | 
| Dhruvaraj Subhashchandran | e29be41 | 2018-01-16 05:11:56 -0600 | [diff] [blame] | 757 |     for (auto cap : caps->second.capList) | 
 | 758 |     { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 759 |         // If the data is beyond first byte boundary, insert in a | 
 | 760 |         // 16bit pattern for example number of SEL entries are represented | 
 | 761 |         // in 12bits. | 
| Dhruvaraj Subhashchandran | e29be41 | 2018-01-16 05:11:56 -0600 | [diff] [blame] | 762 |         if ((cap.length + cap.position) > 8) | 
 | 763 |         { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 764 |             // Read the value corresponding to capability name and assign to | 
 | 765 |             // 16bit bitset. | 
| Dhruvaraj Subhashchandran | e29be41 | 2018-01-16 05:11:56 -0600 | [diff] [blame] | 766 |             std::bitset<16> val(data.value(cap.name.c_str(), 0)); | 
 | 767 |             val <<= cap.position; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 768 |             reinterpret_cast<uint16_t*>( | 
 | 769 |                 responseData | 
 | 770 |                     ->data)[(cap.bytePosition - 1) / sizeof(uint16_t)] |= | 
 | 771 |                 val.to_ulong(); | 
| Dhruvaraj Subhashchandran | e29be41 | 2018-01-16 05:11:56 -0600 | [diff] [blame] | 772 |         } | 
 | 773 |         else | 
 | 774 |         { | 
 | 775 |             responseData->data[cap.bytePosition - 1] |= | 
 | 776 |                 data.value(cap.name.c_str(), 0) << cap.position; | 
 | 777 |         } | 
 | 778 |     } | 
 | 779 |  | 
 | 780 |     responseData->groupID = dcmi::groupExtId; | 
 | 781 |     responseData->major = DCMI_SPEC_MAJOR_VERSION; | 
 | 782 |     responseData->minor = DCMI_SPEC_MINOR_VERSION; | 
 | 783 |     responseData->paramRevision = DCMI_PARAMETER_REVISION; | 
 | 784 |     *data_len = sizeof(*responseData) + caps->second.size; | 
 | 785 |  | 
 | 786 |     return IPMI_CC_OK; | 
 | 787 | } | 
 | 788 |  | 
| Deepak Kodihalli | ee717d7 | 2018-01-24 04:53:09 -0600 | [diff] [blame] | 789 | namespace dcmi | 
 | 790 | { | 
 | 791 | namespace temp_readings | 
 | 792 | { | 
 | 793 |  | 
| Deepak Kodihalli | b1e8fba | 2018-01-24 04:57:10 -0600 | [diff] [blame] | 794 | Temperature readTemp(const std::string& dbusService, | 
 | 795 |                      const std::string& dbusPath) | 
 | 796 | { | 
 | 797 |     // Read the temperature value from d-bus object. Need some conversion. | 
 | 798 |     // As per the interface xyz.openbmc_project.Sensor.Value, the temperature | 
 | 799 |     // is an int64_t and in degrees C. It needs to be scaled by using the | 
 | 800 |     // formula Value * 10^Scale. The ipmi spec has the temperature as a uint8_t, | 
 | 801 |     // with a separate single bit for the sign. | 
 | 802 |  | 
 | 803 |     sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 804 |     auto result = ipmi::getAllDbusProperties( | 
 | 805 |         bus, dbusService, dbusPath, "xyz.openbmc_project.Sensor.Value"); | 
| William A. Kennington III | 4c00802 | 2018-10-12 17:18:14 -0700 | [diff] [blame] | 806 |     auto temperature = variant_ns::get<int64_t>(result.at("Value")); | 
| Deepak Kodihalli | b1e8fba | 2018-01-24 04:57:10 -0600 | [diff] [blame] | 807 |     uint64_t absTemp = std::abs(temperature); | 
 | 808 |  | 
| William A. Kennington III | 4c00802 | 2018-10-12 17:18:14 -0700 | [diff] [blame] | 809 |     auto factor = variant_ns::get<int64_t>(result.at("Scale")); | 
| Deepak Kodihalli | b1e8fba | 2018-01-24 04:57:10 -0600 | [diff] [blame] | 810 |     uint64_t scale = std::pow(10, factor); // pow() returns float/double | 
 | 811 |     unsigned long long tempDegrees = 0; | 
 | 812 |     // Overflow safe multiplication when the scale is > 0 | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 813 |     if (scale && __builtin_umulll_overflow(absTemp, scale, &tempDegrees)) | 
| Deepak Kodihalli | b1e8fba | 2018-01-24 04:57:10 -0600 | [diff] [blame] | 814 |     { | 
 | 815 |         log<level::ERR>("Multiplication overflow detected", | 
 | 816 |                         entry("TEMP_VALUE=%llu", absTemp), | 
 | 817 |                         entry("SCALE_FACTOR=%llu", scale)); | 
 | 818 |         elog<InternalFailure>(); | 
 | 819 |     } | 
 | 820 |     else | 
 | 821 |     { | 
 | 822 |         // The (uint64_t)scale value is 0, effectively this is division | 
 | 823 |         tempDegrees = absTemp * std::pow(10, factor); | 
 | 824 |     } | 
 | 825 |     // Max absolute temp as per ipmi spec is 128. | 
 | 826 |     if (tempDegrees > maxTemp) | 
 | 827 |     { | 
 | 828 |         tempDegrees = maxTemp; | 
 | 829 |     } | 
 | 830 |  | 
 | 831 |     return std::make_tuple(static_cast<uint8_t>(tempDegrees), | 
 | 832 |                            (temperature < 0)); | 
 | 833 | } | 
 | 834 |  | 
| Deepak Kodihalli | ee717d7 | 2018-01-24 04:53:09 -0600 | [diff] [blame] | 835 | std::tuple<Response, NumInstances> read(const std::string& type, | 
 | 836 |                                         uint8_t instance) | 
 | 837 | { | 
| Deepak Kodihalli | b1e8fba | 2018-01-24 04:57:10 -0600 | [diff] [blame] | 838 |     Response response{}; | 
 | 839 |     sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; | 
 | 840 |  | 
 | 841 |     if (!instance) | 
 | 842 |     { | 
 | 843 |         log<level::ERR>("Expected non-zero instance"); | 
 | 844 |         elog<InternalFailure>(); | 
 | 845 |     } | 
 | 846 |  | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 847 |     auto data = parseSensorConfig(); | 
| Deepak Kodihalli | b1e8fba | 2018-01-24 04:57:10 -0600 | [diff] [blame] | 848 |     static const std::vector<Json> empty{}; | 
 | 849 |     std::vector<Json> readings = data.value(type, empty); | 
 | 850 |     size_t numInstances = readings.size(); | 
 | 851 |     for (const auto& j : readings) | 
 | 852 |     { | 
 | 853 |         uint8_t instanceNum = j.value("instance", 0); | 
 | 854 |         // Not the instance we're interested in | 
 | 855 |         if (instanceNum != instance) | 
 | 856 |         { | 
 | 857 |             continue; | 
 | 858 |         } | 
 | 859 |  | 
 | 860 |         std::string path = j.value("dbus", ""); | 
 | 861 |         std::string service; | 
 | 862 |         try | 
 | 863 |         { | 
 | 864 |             service = | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 865 |                 ipmi::getService(bus, "xyz.openbmc_project.Sensor.Value", path); | 
| Deepak Kodihalli | b1e8fba | 2018-01-24 04:57:10 -0600 | [diff] [blame] | 866 |         } | 
 | 867 |         catch (std::exception& e) | 
 | 868 |         { | 
 | 869 |             log<level::DEBUG>(e.what()); | 
 | 870 |             return std::make_tuple(response, numInstances); | 
 | 871 |         } | 
 | 872 |  | 
 | 873 |         response.instance = instance; | 
 | 874 |         uint8_t temp{}; | 
 | 875 |         bool sign{}; | 
 | 876 |         std::tie(temp, sign) = readTemp(service, path); | 
 | 877 |         response.temperature = temp; | 
 | 878 |         response.sign = sign; | 
 | 879 |  | 
 | 880 |         // Found the instance we're interested in | 
 | 881 |         break; | 
 | 882 |     } | 
 | 883 |  | 
 | 884 |     if (numInstances > maxInstances) | 
 | 885 |     { | 
 | 886 |         numInstances = maxInstances; | 
 | 887 |     } | 
 | 888 |     return std::make_tuple(response, numInstances); | 
| Deepak Kodihalli | ee717d7 | 2018-01-24 04:53:09 -0600 | [diff] [blame] | 889 | } | 
 | 890 |  | 
 | 891 | std::tuple<ResponseList, NumInstances> readAll(const std::string& type, | 
 | 892 |                                                uint8_t instanceStart) | 
 | 893 | { | 
| Deepak Kodihalli | b1e8fba | 2018-01-24 04:57:10 -0600 | [diff] [blame] | 894 |     ResponseList response{}; | 
 | 895 |     sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; | 
 | 896 |  | 
 | 897 |     size_t numInstances = 0; | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 898 |     auto data = parseSensorConfig(); | 
| Deepak Kodihalli | b1e8fba | 2018-01-24 04:57:10 -0600 | [diff] [blame] | 899 |     static const std::vector<Json> empty{}; | 
 | 900 |     std::vector<Json> readings = data.value(type, empty); | 
 | 901 |     numInstances = readings.size(); | 
 | 902 |     for (const auto& j : readings) | 
 | 903 |     { | 
 | 904 |         try | 
 | 905 |         { | 
 | 906 |             // Max of 8 response data sets | 
 | 907 |             if (response.size() == maxDataSets) | 
 | 908 |             { | 
 | 909 |                 break; | 
 | 910 |             } | 
 | 911 |  | 
 | 912 |             uint8_t instanceNum = j.value("instance", 0); | 
 | 913 |             // Not in the instance range we're interested in | 
 | 914 |             if (instanceNum < instanceStart) | 
 | 915 |             { | 
 | 916 |                 continue; | 
 | 917 |             } | 
 | 918 |  | 
 | 919 |             std::string path = j.value("dbus", ""); | 
 | 920 |             auto service = | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 921 |                 ipmi::getService(bus, "xyz.openbmc_project.Sensor.Value", path); | 
| Deepak Kodihalli | b1e8fba | 2018-01-24 04:57:10 -0600 | [diff] [blame] | 922 |  | 
 | 923 |             Response r{}; | 
 | 924 |             r.instance = instanceNum; | 
 | 925 |             uint8_t temp{}; | 
 | 926 |             bool sign{}; | 
 | 927 |             std::tie(temp, sign) = readTemp(service, path); | 
 | 928 |             r.temperature = temp; | 
 | 929 |             r.sign = sign; | 
 | 930 |             response.push_back(r); | 
 | 931 |         } | 
 | 932 |         catch (std::exception& e) | 
 | 933 |         { | 
 | 934 |             log<level::DEBUG>(e.what()); | 
 | 935 |             continue; | 
 | 936 |         } | 
 | 937 |     } | 
 | 938 |  | 
 | 939 |     if (numInstances > maxInstances) | 
 | 940 |     { | 
 | 941 |         numInstances = maxInstances; | 
 | 942 |     } | 
 | 943 |     return std::make_tuple(response, numInstances); | 
| Deepak Kodihalli | ee717d7 | 2018-01-24 04:53:09 -0600 | [diff] [blame] | 944 | } | 
 | 945 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 946 | } // namespace temp_readings | 
 | 947 | } // namespace dcmi | 
| Deepak Kodihalli | ee717d7 | 2018-01-24 04:53:09 -0600 | [diff] [blame] | 948 |  | 
 | 949 | ipmi_ret_t getTempReadings(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 950 |                            ipmi_request_t request, ipmi_response_t response, | 
 | 951 |                            ipmi_data_len_t data_len, ipmi_context_t context) | 
| Deepak Kodihalli | ee717d7 | 2018-01-24 04:53:09 -0600 | [diff] [blame] | 952 | { | 
| Deepak Kodihalli | ee717d7 | 2018-01-24 04:53:09 -0600 | [diff] [blame] | 953 |     auto requestData = | 
 | 954 |         reinterpret_cast<const dcmi::GetTempReadingsRequest*>(request); | 
 | 955 |     auto responseData = | 
 | 956 |         reinterpret_cast<dcmi::GetTempReadingsResponseHdr*>(response); | 
 | 957 |  | 
 | 958 |     if (*data_len != sizeof(dcmi::GetTempReadingsRequest)) | 
 | 959 |     { | 
 | 960 |         log<level::ERR>("Malformed request data", | 
 | 961 |                         entry("DATA_SIZE=%d", *data_len)); | 
 | 962 |         return IPMI_CC_REQ_DATA_LEN_INVALID; | 
 | 963 |     } | 
 | 964 |     *data_len = 0; | 
 | 965 |  | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 966 |     auto it = dcmi::entityIdToName.find(requestData->entityId); | 
 | 967 |     if (it == dcmi::entityIdToName.end()) | 
| Deepak Kodihalli | ee717d7 | 2018-01-24 04:53:09 -0600 | [diff] [blame] | 968 |     { | 
 | 969 |         log<level::ERR>("Unknown Entity ID", | 
 | 970 |                         entry("ENTITY_ID=%d", requestData->entityId)); | 
 | 971 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 972 |     } | 
 | 973 |  | 
 | 974 |     if (requestData->groupID != dcmi::groupExtId) | 
 | 975 |     { | 
 | 976 |         log<level::ERR>("Invalid Group ID", | 
 | 977 |                         entry("GROUP_ID=%d", requestData->groupID)); | 
 | 978 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 979 |     } | 
 | 980 |  | 
 | 981 |     if (requestData->sensorType != dcmi::temperatureSensorType) | 
 | 982 |     { | 
 | 983 |         log<level::ERR>("Invalid sensor type", | 
 | 984 |                         entry("SENSOR_TYPE=%d", requestData->sensorType)); | 
 | 985 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 986 |     } | 
 | 987 |  | 
 | 988 |     dcmi::temp_readings::ResponseList temps{}; | 
 | 989 |     try | 
 | 990 |     { | 
 | 991 |         if (!requestData->entityInstance) | 
 | 992 |         { | 
 | 993 |             // Read all instances | 
 | 994 |             std::tie(temps, responseData->numInstances) = | 
 | 995 |                 dcmi::temp_readings::readAll(it->second, | 
 | 996 |                                              requestData->instanceStart); | 
 | 997 |         } | 
 | 998 |         else | 
 | 999 |         { | 
 | 1000 |             // Read one instance | 
 | 1001 |             temps.resize(1); | 
 | 1002 |             std::tie(temps[0], responseData->numInstances) = | 
 | 1003 |                 dcmi::temp_readings::read(it->second, | 
 | 1004 |                                           requestData->entityInstance); | 
 | 1005 |         } | 
 | 1006 |         responseData->numDataSets = temps.size(); | 
 | 1007 |     } | 
 | 1008 |     catch (InternalFailure& e) | 
 | 1009 |     { | 
 | 1010 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 1011 |     } | 
 | 1012 |  | 
 | 1013 |     responseData->groupID = dcmi::groupExtId; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1014 |     size_t payloadSize = temps.size() * sizeof(dcmi::temp_readings::Response); | 
| Deepak Kodihalli | ee717d7 | 2018-01-24 04:53:09 -0600 | [diff] [blame] | 1015 |     if (!temps.empty()) | 
 | 1016 |     { | 
 | 1017 |         memcpy(responseData + 1, // copy payload right after the response header | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1018 |                temps.data(), payloadSize); | 
| Deepak Kodihalli | ee717d7 | 2018-01-24 04:53:09 -0600 | [diff] [blame] | 1019 |     } | 
 | 1020 |     *data_len = sizeof(dcmi::GetTempReadingsResponseHdr) + payloadSize; | 
 | 1021 |  | 
 | 1022 |     return IPMI_CC_OK; | 
 | 1023 | } | 
 | 1024 |  | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 1025 | int64_t getPowerReading(sdbusplus::bus::bus& bus) | 
 | 1026 | { | 
 | 1027 |     std::ifstream sensorFile(POWER_READING_SENSOR); | 
 | 1028 |     std::string objectPath; | 
 | 1029 |     if (!sensorFile.is_open()) | 
 | 1030 |     { | 
 | 1031 |         log<level::ERR>("Power reading configuration file not found", | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1032 |                         entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR)); | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 1033 |         elog<InternalFailure>(); | 
 | 1034 |     } | 
 | 1035 |  | 
 | 1036 |     auto data = nlohmann::json::parse(sensorFile, nullptr, false); | 
 | 1037 |     if (data.is_discarded()) | 
 | 1038 |     { | 
 | 1039 |         log<level::ERR>("Error in parsing configuration file", | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1040 |                         entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR)); | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 1041 |         elog<InternalFailure>(); | 
 | 1042 |     } | 
 | 1043 |  | 
 | 1044 |     objectPath = data.value("path", ""); | 
 | 1045 |     if (objectPath.empty()) | 
 | 1046 |     { | 
 | 1047 |         log<level::ERR>("Power sensor D-Bus object path is empty", | 
 | 1048 |                         entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR)); | 
 | 1049 |         elog<InternalFailure>(); | 
 | 1050 |     } | 
 | 1051 |  | 
| Marri Devender Rao | ce6a795 | 2018-02-11 08:45:00 -0600 | [diff] [blame] | 1052 |     // Return default value if failed to read from D-Bus object | 
 | 1053 |     int64_t power = 0; | 
 | 1054 |     try | 
 | 1055 |     { | 
 | 1056 |         auto service = ipmi::getService(bus, SENSOR_VALUE_INTF, objectPath); | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 1057 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1058 |         // Read the sensor value and scale properties | 
 | 1059 |         auto properties = ipmi::getAllDbusProperties(bus, service, objectPath, | 
 | 1060 |                                                      SENSOR_VALUE_INTF); | 
| William A. Kennington III | 4c00802 | 2018-10-12 17:18:14 -0700 | [diff] [blame] | 1061 |         auto value = variant_ns::get<int64_t>(properties[SENSOR_VALUE_PROP]); | 
 | 1062 |         auto scale = variant_ns::get<int64_t>(properties[SENSOR_SCALE_PROP]); | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 1063 |  | 
| Marri Devender Rao | ce6a795 | 2018-02-11 08:45:00 -0600 | [diff] [blame] | 1064 |         // Power reading needs to be scaled with the Scale value using the | 
 | 1065 |         // formula Value * 10^Scale. | 
 | 1066 |         power = value * std::pow(10, scale); | 
 | 1067 |     } | 
 | 1068 |     catch (std::exception& e) | 
 | 1069 |     { | 
 | 1070 |         log<level::INFO>("Failure to read power value from D-Bus object", | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1071 |                          entry("OBJECT_PATH=%s", objectPath.c_str()), | 
 | 1072 |                          entry("INTERFACE=%s", SENSOR_VALUE_INTF)); | 
| Marri Devender Rao | ce6a795 | 2018-02-11 08:45:00 -0600 | [diff] [blame] | 1073 |     } | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 1074 |     return power; | 
 | 1075 | } | 
 | 1076 |  | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1077 | ipmi_ret_t setDCMIConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
 | 1078 |                              ipmi_request_t request, ipmi_response_t response, | 
 | 1079 |                              ipmi_data_len_t data_len, ipmi_context_t context) | 
 | 1080 | { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1081 |     auto requestData = | 
 | 1082 |         reinterpret_cast<const dcmi::SetConfParamsRequest*>(request); | 
 | 1083 |     auto responseData = | 
 | 1084 |         reinterpret_cast<dcmi::SetConfParamsResponse*>(response); | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1085 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1086 |     if (requestData->groupID != dcmi::groupExtId || | 
 | 1087 |         *data_len < DCMI_SET_CONF_PARAM_REQ_PACKET_MIN_SIZE || | 
 | 1088 |         *data_len > DCMI_SET_CONF_PARAM_REQ_PACKET_MAX_SIZE) | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1089 |     { | 
| Gunnar Mills | 8466b79 | 2018-03-23 12:18:12 -0500 | [diff] [blame] | 1090 |         log<level::ERR>("Invalid Group ID or Invalid Requested Packet size", | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1091 |                         entry("GROUP_ID=%d", requestData->groupID), | 
 | 1092 |                         entry("PACKET SIZE=%d", *data_len)); | 
 | 1093 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 1094 |     } | 
 | 1095 |  | 
 | 1096 |     *data_len = 0; | 
 | 1097 |  | 
 | 1098 |     try | 
 | 1099 |     { | 
 | 1100 |         // Take action based on the Parameter Selector | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1101 |         switch ( | 
 | 1102 |             static_cast<dcmi::DCMIConfigParameters>(requestData->paramSelect)) | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1103 |         { | 
 | 1104 |             case dcmi::DCMIConfigParameters::ActivateDHCP: | 
 | 1105 |  | 
 | 1106 |                 if ((requestData->data[0] & DCMI_ACTIVATE_DHCP_MASK) && | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1107 |                     dcmi::getDHCPEnabled()) | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1108 |                 { | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1109 |                     // When these conditions are met we have to trigger DHCP | 
 | 1110 |                     // protocol restart using the latest parameter settings, but | 
 | 1111 |                     // as per n/w manager design, each time when we update n/w | 
 | 1112 |                     // parameters, n/w service is restarted. So we no need to | 
 | 1113 |                     // take any action in this case. | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1114 |                 } | 
 | 1115 |                 break; | 
 | 1116 |  | 
 | 1117 |             case dcmi::DCMIConfigParameters::DiscoveryConfig: | 
 | 1118 |  | 
 | 1119 |                 if (requestData->data[0] & DCMI_OPTION_12_MASK) | 
 | 1120 |                 { | 
 | 1121 |                     dcmi::setDHCPOption(DHCP_OPT12_ENABLED, true); | 
 | 1122 |                 } | 
 | 1123 |                 else | 
 | 1124 |                 { | 
 | 1125 |                     dcmi::setDHCPOption(DHCP_OPT12_ENABLED, false); | 
 | 1126 |                 } | 
 | 1127 |  | 
 | 1128 |                 // Systemd-networkd doesn't support Random Back off | 
 | 1129 |                 if (requestData->data[0] & DCMI_RAND_BACK_OFF_MASK) | 
 | 1130 |                 { | 
 | 1131 |                     return IPMI_CC_INVALID; | 
 | 1132 |                 } | 
 | 1133 |                 break; | 
 | 1134 |             // Systemd-networkd doesn't allow to configure DHCP timigs | 
 | 1135 |             case dcmi::DCMIConfigParameters::DHCPTiming1: | 
 | 1136 |             case dcmi::DCMIConfigParameters::DHCPTiming2: | 
 | 1137 |             case dcmi::DCMIConfigParameters::DHCPTiming3: | 
 | 1138 |             default: | 
 | 1139 |                 return IPMI_CC_INVALID; | 
 | 1140 |         } | 
 | 1141 |     } | 
 | 1142 |     catch (std::exception& e) | 
 | 1143 |     { | 
 | 1144 |         log<level::ERR>(e.what()); | 
 | 1145 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 1146 |     } | 
 | 1147 |     responseData->groupID = dcmi::groupExtId; | 
 | 1148 |     *data_len = sizeof(dcmi::SetConfParamsResponse); | 
 | 1149 |  | 
 | 1150 |     return IPMI_CC_OK; | 
 | 1151 | } | 
 | 1152 |  | 
 | 1153 | ipmi_ret_t getDCMIConfParams(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
 | 1154 |                              ipmi_request_t request, ipmi_response_t response, | 
 | 1155 |                              ipmi_data_len_t data_len, ipmi_context_t context) | 
 | 1156 | { | 
 | 1157 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1158 |     auto requestData = | 
 | 1159 |         reinterpret_cast<const dcmi::GetConfParamsRequest*>(request); | 
 | 1160 |     auto responseData = | 
 | 1161 |         reinterpret_cast<dcmi::GetConfParamsResponse*>(response); | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1162 |  | 
 | 1163 |     responseData->data[0] = 0x00; | 
 | 1164 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1165 |     if (requestData->groupID != dcmi::groupExtId || | 
 | 1166 |         *data_len != sizeof(dcmi::GetConfParamsRequest)) | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1167 |     { | 
| Gunnar Mills | 8466b79 | 2018-03-23 12:18:12 -0500 | [diff] [blame] | 1168 |         log<level::ERR>("Invalid Group ID or Invalid Requested Packet size", | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1169 |                         entry("GROUP_ID=%d", requestData->groupID), | 
 | 1170 |                         entry("PACKET SIZE=%d", *data_len)); | 
 | 1171 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 1172 |     } | 
 | 1173 |  | 
 | 1174 |     *data_len = 0; | 
 | 1175 |  | 
 | 1176 |     try | 
 | 1177 |     { | 
 | 1178 |         // Take action based on the Parameter Selector | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1179 |         switch ( | 
 | 1180 |             static_cast<dcmi::DCMIConfigParameters>(requestData->paramSelect)) | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1181 |         { | 
 | 1182 |             case dcmi::DCMIConfigParameters::ActivateDHCP: | 
 | 1183 |                 responseData->data[0] = DCMI_ACTIVATE_DHCP_REPLY; | 
 | 1184 |                 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1; | 
 | 1185 |                 break; | 
 | 1186 |             case dcmi::DCMIConfigParameters::DiscoveryConfig: | 
 | 1187 |                 if (dcmi::getDHCPOption(DHCP_OPT12_ENABLED)) | 
 | 1188 |                 { | 
 | 1189 |                     responseData->data[0] |= DCMI_OPTION_12_MASK; | 
 | 1190 |                 } | 
 | 1191 |                 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1; | 
 | 1192 |                 break; | 
 | 1193 |             // Get below values from Systemd-networkd source code | 
 | 1194 |             case dcmi::DCMIConfigParameters::DHCPTiming1: | 
 | 1195 |                 responseData->data[0] = DHCP_TIMING1; | 
 | 1196 |                 *data_len = sizeof(dcmi::GetConfParamsResponse) + 1; | 
 | 1197 |                 break; | 
 | 1198 |             case dcmi::DCMIConfigParameters::DHCPTiming2: | 
 | 1199 |                 responseData->data[0] = DHCP_TIMING2_LOWER; | 
 | 1200 |                 responseData->data[1] = DHCP_TIMING2_UPPER; | 
 | 1201 |                 *data_len = sizeof(dcmi::GetConfParamsResponse) + 2; | 
 | 1202 |                 break; | 
 | 1203 |             case dcmi::DCMIConfigParameters::DHCPTiming3: | 
 | 1204 |                 responseData->data[0] = DHCP_TIMING3_LOWER; | 
 | 1205 |                 responseData->data[1] = DHCP_TIMING3_UPPER; | 
 | 1206 |                 *data_len = sizeof(dcmi::GetConfParamsResponse) + 2; | 
 | 1207 |                 break; | 
 | 1208 |             default: | 
 | 1209 |                 *data_len = 0; | 
 | 1210 |                 return IPMI_CC_INVALID; | 
 | 1211 |         } | 
 | 1212 |     } | 
 | 1213 |     catch (std::exception& e) | 
 | 1214 |     { | 
 | 1215 |         log<level::ERR>(e.what()); | 
 | 1216 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 1217 |     } | 
 | 1218 |  | 
 | 1219 |     responseData->groupID = dcmi::groupExtId; | 
 | 1220 |     responseData->major = DCMI_SPEC_MAJOR_VERSION; | 
 | 1221 |     responseData->minor = DCMI_SPEC_MINOR_VERSION; | 
 | 1222 |     responseData->paramRevision = DCMI_CONFIG_PARAMETER_REVISION; | 
 | 1223 |  | 
 | 1224 |     return IPMI_CC_OK; | 
 | 1225 | } | 
 | 1226 |  | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 1227 | ipmi_ret_t getPowerReading(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1228 |                            ipmi_request_t request, ipmi_response_t response, | 
 | 1229 |                            ipmi_data_len_t data_len, ipmi_context_t context) | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 1230 | { | 
 | 1231 |     ipmi_ret_t rc = IPMI_CC_OK; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1232 |     auto requestData = | 
 | 1233 |         reinterpret_cast<const dcmi::GetPowerReadingRequest*>(request); | 
 | 1234 |     auto responseData = | 
 | 1235 |         reinterpret_cast<dcmi::GetPowerReadingResponse*>(response); | 
| Marri Devender Rao | 9c966e0 | 2018-01-22 05:55:10 -0600 | [diff] [blame] | 1236 |  | 
 | 1237 |     if (requestData->groupID != dcmi::groupExtId) | 
 | 1238 |     { | 
 | 1239 |         *data_len = 0; | 
 | 1240 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 1241 |     } | 
 | 1242 |  | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 1243 |     sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; | 
| Marri Devender Rao | 9c966e0 | 2018-01-22 05:55:10 -0600 | [diff] [blame] | 1244 |     int64_t power = 0; | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 1245 |     try | 
 | 1246 |     { | 
| Marri Devender Rao | 9c966e0 | 2018-01-22 05:55:10 -0600 | [diff] [blame] | 1247 |         power = getPowerReading(bus); | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 1248 |     } | 
 | 1249 |     catch (InternalFailure& e) | 
 | 1250 |     { | 
 | 1251 |         log<level::ERR>("Error in reading power sensor value", | 
 | 1252 |                         entry("INTERFACE=%s", SENSOR_VALUE_INTF), | 
 | 1253 |                         entry("PROPERTY=%s", SENSOR_VALUE_PROP)); | 
 | 1254 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 1255 |     } | 
| Marri Devender Rao | 9c966e0 | 2018-01-22 05:55:10 -0600 | [diff] [blame] | 1256 |     responseData->groupID = dcmi::groupExtId; | 
 | 1257 |  | 
 | 1258 |     // TODO: openbmc/openbmc#2819 | 
| Gunnar Mills | 8466b79 | 2018-03-23 12:18:12 -0500 | [diff] [blame] | 1259 |     // Minimum, Maximum, Average power, TimeFrame, TimeStamp, | 
| Marri Devender Rao | 9c966e0 | 2018-01-22 05:55:10 -0600 | [diff] [blame] | 1260 |     // PowerReadingState readings need to be populated | 
 | 1261 |     // after Telemetry changes. | 
 | 1262 |     uint16_t totalPower = static_cast<uint16_t>(power); | 
 | 1263 |     responseData->currentPower = totalPower; | 
 | 1264 |     responseData->minimumPower = totalPower; | 
 | 1265 |     responseData->maximumPower = totalPower; | 
 | 1266 |     responseData->averagePower = totalPower; | 
 | 1267 |  | 
 | 1268 |     *data_len = sizeof(*responseData); | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 1269 |     return rc; | 
 | 1270 | } | 
 | 1271 |  | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 1272 | namespace dcmi | 
 | 1273 | { | 
 | 1274 | namespace sensor_info | 
 | 1275 | { | 
 | 1276 |  | 
| Deepak Kodihalli | dd4cff1 | 2018-02-06 06:48:29 -0600 | [diff] [blame] | 1277 | Response createFromJson(const Json& config) | 
 | 1278 | { | 
 | 1279 |     Response response{}; | 
 | 1280 |     uint16_t recordId = config.value("record_id", 0); | 
 | 1281 |     response.recordIdLsb = recordId & 0xFF; | 
 | 1282 |     response.recordIdMsb = (recordId >> 8) & 0xFF; | 
 | 1283 |     return response; | 
 | 1284 | } | 
 | 1285 |  | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 1286 | std::tuple<Response, NumInstances> read(const std::string& type, | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1287 |                                         uint8_t instance, const Json& config) | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 1288 | { | 
| Deepak Kodihalli | dd4cff1 | 2018-02-06 06:48:29 -0600 | [diff] [blame] | 1289 |     Response response{}; | 
 | 1290 |  | 
 | 1291 |     if (!instance) | 
 | 1292 |     { | 
 | 1293 |         log<level::ERR>("Expected non-zero instance"); | 
 | 1294 |         elog<InternalFailure>(); | 
 | 1295 |     } | 
 | 1296 |  | 
 | 1297 |     static const std::vector<Json> empty{}; | 
 | 1298 |     std::vector<Json> readings = config.value(type, empty); | 
 | 1299 |     size_t numInstances = readings.size(); | 
 | 1300 |     for (const auto& reading : readings) | 
 | 1301 |     { | 
 | 1302 |         uint8_t instanceNum = reading.value("instance", 0); | 
 | 1303 |         // Not the instance we're interested in | 
 | 1304 |         if (instanceNum != instance) | 
 | 1305 |         { | 
 | 1306 |             continue; | 
 | 1307 |         } | 
 | 1308 |  | 
 | 1309 |         response = createFromJson(reading); | 
 | 1310 |  | 
 | 1311 |         // Found the instance we're interested in | 
 | 1312 |         break; | 
 | 1313 |     } | 
 | 1314 |  | 
 | 1315 |     if (numInstances > maxInstances) | 
 | 1316 |     { | 
 | 1317 |         log<level::DEBUG>("Trimming IPMI num instances", | 
 | 1318 |                           entry("NUM_INSTANCES=%d", numInstances)); | 
 | 1319 |         numInstances = maxInstances; | 
 | 1320 |     } | 
 | 1321 |     return std::make_tuple(response, numInstances); | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 1322 | } | 
 | 1323 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1324 | std::tuple<ResponseList, NumInstances> | 
 | 1325 |     readAll(const std::string& type, uint8_t instanceStart, const Json& config) | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 1326 | { | 
| Deepak Kodihalli | dd4cff1 | 2018-02-06 06:48:29 -0600 | [diff] [blame] | 1327 |     ResponseList responses{}; | 
 | 1328 |  | 
 | 1329 |     size_t numInstances = 0; | 
 | 1330 |     static const std::vector<Json> empty{}; | 
 | 1331 |     std::vector<Json> readings = config.value(type, empty); | 
 | 1332 |     numInstances = readings.size(); | 
 | 1333 |     for (const auto& reading : readings) | 
 | 1334 |     { | 
 | 1335 |         try | 
 | 1336 |         { | 
 | 1337 |             // Max of 8 records | 
 | 1338 |             if (responses.size() == maxRecords) | 
 | 1339 |             { | 
 | 1340 |                 break; | 
 | 1341 |             } | 
 | 1342 |  | 
 | 1343 |             uint8_t instanceNum = reading.value("instance", 0); | 
 | 1344 |             // Not in the instance range we're interested in | 
 | 1345 |             if (instanceNum < instanceStart) | 
 | 1346 |             { | 
 | 1347 |                 continue; | 
 | 1348 |             } | 
 | 1349 |  | 
 | 1350 |             Response response = createFromJson(reading); | 
 | 1351 |             responses.push_back(response); | 
 | 1352 |         } | 
 | 1353 |         catch (std::exception& e) | 
 | 1354 |         { | 
 | 1355 |             log<level::DEBUG>(e.what()); | 
 | 1356 |             continue; | 
 | 1357 |         } | 
 | 1358 |     } | 
 | 1359 |  | 
 | 1360 |     if (numInstances > maxInstances) | 
 | 1361 |     { | 
 | 1362 |         log<level::DEBUG>("Trimming IPMI num instances", | 
 | 1363 |                           entry("NUM_INSTANCES=%d", numInstances)); | 
 | 1364 |         numInstances = maxInstances; | 
 | 1365 |     } | 
 | 1366 |     return std::make_tuple(responses, numInstances); | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 1367 | } | 
 | 1368 |  | 
 | 1369 | } // namespace sensor_info | 
 | 1370 | } // namespace dcmi | 
 | 1371 |  | 
 | 1372 | ipmi_ret_t getSensorInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
 | 1373 |                          ipmi_request_t request, ipmi_response_t response, | 
 | 1374 |                          ipmi_data_len_t data_len, ipmi_context_t context) | 
 | 1375 | { | 
 | 1376 |     auto requestData = | 
 | 1377 |         reinterpret_cast<const dcmi::GetSensorInfoRequest*>(request); | 
 | 1378 |     auto responseData = | 
 | 1379 |         reinterpret_cast<dcmi::GetSensorInfoResponseHdr*>(response); | 
 | 1380 |  | 
 | 1381 |     if (*data_len != sizeof(dcmi::GetSensorInfoRequest)) | 
 | 1382 |     { | 
 | 1383 |         log<level::ERR>("Malformed request data", | 
 | 1384 |                         entry("DATA_SIZE=%d", *data_len)); | 
 | 1385 |         return IPMI_CC_REQ_DATA_LEN_INVALID; | 
 | 1386 |     } | 
 | 1387 |     *data_len = 0; | 
 | 1388 |  | 
 | 1389 |     auto it = dcmi::entityIdToName.find(requestData->entityId); | 
 | 1390 |     if (it == dcmi::entityIdToName.end()) | 
 | 1391 |     { | 
 | 1392 |         log<level::ERR>("Unknown Entity ID", | 
 | 1393 |                         entry("ENTITY_ID=%d", requestData->entityId)); | 
 | 1394 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 1395 |     } | 
 | 1396 |  | 
 | 1397 |     if (requestData->groupID != dcmi::groupExtId) | 
 | 1398 |     { | 
 | 1399 |         log<level::ERR>("Invalid Group ID", | 
 | 1400 |                         entry("GROUP_ID=%d", requestData->groupID)); | 
 | 1401 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 1402 |     } | 
 | 1403 |  | 
 | 1404 |     if (requestData->sensorType != dcmi::temperatureSensorType) | 
 | 1405 |     { | 
 | 1406 |         log<level::ERR>("Invalid sensor type", | 
 | 1407 |                         entry("SENSOR_TYPE=%d", requestData->sensorType)); | 
 | 1408 |         return IPMI_CC_INVALID_FIELD_REQUEST; | 
 | 1409 |     } | 
 | 1410 |  | 
 | 1411 |     dcmi::sensor_info::ResponseList sensors{}; | 
 | 1412 |     static dcmi::Json config{}; | 
 | 1413 |     static bool parsed = false; | 
 | 1414 |  | 
 | 1415 |     try | 
 | 1416 |     { | 
 | 1417 |         if (!parsed) | 
 | 1418 |         { | 
 | 1419 |             config = dcmi::parseSensorConfig(); | 
 | 1420 |             parsed = true; | 
 | 1421 |         } | 
 | 1422 |  | 
 | 1423 |         if (!requestData->entityInstance) | 
 | 1424 |         { | 
 | 1425 |             // Read all instances | 
 | 1426 |             std::tie(sensors, responseData->numInstances) = | 
 | 1427 |                 dcmi::sensor_info::readAll(it->second, | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1428 |                                            requestData->instanceStart, config); | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 1429 |         } | 
 | 1430 |         else | 
 | 1431 |         { | 
 | 1432 |             // Read one instance | 
 | 1433 |             sensors.resize(1); | 
 | 1434 |             std::tie(sensors[0], responseData->numInstances) = | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1435 |                 dcmi::sensor_info::read(it->second, requestData->entityInstance, | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 1436 |                                         config); | 
 | 1437 |         } | 
 | 1438 |         responseData->numRecords = sensors.size(); | 
 | 1439 |     } | 
 | 1440 |     catch (InternalFailure& e) | 
 | 1441 |     { | 
 | 1442 |         return IPMI_CC_UNSPECIFIED_ERROR; | 
 | 1443 |     } | 
 | 1444 |  | 
 | 1445 |     responseData->groupID = dcmi::groupExtId; | 
 | 1446 |     size_t payloadSize = sensors.size() * sizeof(dcmi::sensor_info::Response); | 
 | 1447 |     if (!sensors.empty()) | 
 | 1448 |     { | 
 | 1449 |         memcpy(responseData + 1, // copy payload right after the response header | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1450 |                sensors.data(), payloadSize); | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 1451 |     } | 
 | 1452 |     *data_len = sizeof(dcmi::GetSensorInfoResponseHdr) + payloadSize; | 
 | 1453 |  | 
 | 1454 |     return IPMI_CC_OK; | 
 | 1455 | } | 
 | 1456 |  | 
| Chris Austen | 1810bec | 2015-10-13 12:12:39 -0500 | [diff] [blame] | 1457 | void register_netfn_dcmi_functions() | 
 | 1458 | { | 
| Tom | 0573237 | 2016-09-06 17:21:23 +0530 | [diff] [blame] | 1459 |     // <Get Power Limit> | 
| Ratan Gupta | 11ddbd2 | 2017-08-05 11:59:39 +0530 | [diff] [blame] | 1460 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1461 |     ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_POWER_LIMIT, NULL, | 
 | 1462 |                            getPowerLimit, PRIVILEGE_USER); | 
| Tom Joseph | 6f6dd4d | 2017-07-12 20:07:11 +0530 | [diff] [blame] | 1463 |  | 
| Tom Joseph | 46fa37d | 2017-07-26 18:11:55 +0530 | [diff] [blame] | 1464 |     // <Set Power Limit> | 
| Ratan Gupta | 11ddbd2 | 2017-08-05 11:59:39 +0530 | [diff] [blame] | 1465 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1466 |     ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_POWER_LIMIT, NULL, | 
 | 1467 |                            setPowerLimit, PRIVILEGE_OPERATOR); | 
| Tom Joseph | 46fa37d | 2017-07-26 18:11:55 +0530 | [diff] [blame] | 1468 |  | 
| Tom Joseph | 6c8d51b | 2017-07-26 18:18:06 +0530 | [diff] [blame] | 1469 |     // <Activate/Deactivate Power Limit> | 
| Ratan Gupta | 11ddbd2 | 2017-08-05 11:59:39 +0530 | [diff] [blame] | 1470 |  | 
 | 1471 |     ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::APPLY_POWER_LIMIT, | 
 | 1472 |                            NULL, applyPowerLimit, PRIVILEGE_OPERATOR); | 
| Tom Joseph | 6c8d51b | 2017-07-26 18:18:06 +0530 | [diff] [blame] | 1473 |  | 
| Tom Joseph | 6f6dd4d | 2017-07-12 20:07:11 +0530 | [diff] [blame] | 1474 |     // <Get Asset Tag> | 
| Ratan Gupta | 11ddbd2 | 2017-08-05 11:59:39 +0530 | [diff] [blame] | 1475 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1476 |     ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_ASSET_TAG, NULL, | 
 | 1477 |                            getAssetTag, PRIVILEGE_USER); | 
| Tom Joseph | 545dd23 | 2017-07-12 20:20:49 +0530 | [diff] [blame] | 1478 |  | 
 | 1479 |     // <Set Asset Tag> | 
| Ratan Gupta | 11ddbd2 | 2017-08-05 11:59:39 +0530 | [diff] [blame] | 1480 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1481 |     ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_ASSET_TAG, NULL, | 
 | 1482 |                            setAssetTag, PRIVILEGE_OPERATOR); | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 1483 |  | 
| Gunnar Mills | 8991dd6 | 2017-10-25 17:11:29 -0500 | [diff] [blame] | 1484 |     // <Get Management Controller Identifier String> | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 1485 |  | 
 | 1486 |     ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_MGMNT_CTRL_ID_STR, | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1487 |                            NULL, getMgmntCtrlIdStr, PRIVILEGE_USER); | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 1488 |  | 
 | 1489 |     // <Set Management Controller Identifier String> | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 1490 |     ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_MGMNT_CTRL_ID_STR, | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1491 |                            NULL, setMgmntCtrlIdStr, PRIVILEGE_ADMIN); | 
| Vladislav Vovchenko | 8f7a6f6 | 2017-08-17 00:31:14 +0300 | [diff] [blame] | 1492 |  | 
| Dhruvaraj Subhashchandran | e29be41 | 2018-01-16 05:11:56 -0600 | [diff] [blame] | 1493 |     // <Get DCMI capabilities> | 
 | 1494 |     ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_CAPABILITIES, | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1495 |                            NULL, getDCMICapabilities, PRIVILEGE_USER); | 
| Deepak Kodihalli | ee717d7 | 2018-01-24 04:53:09 -0600 | [diff] [blame] | 1496 |  | 
 | 1497 |     // <Get Temperature Readings> | 
 | 1498 |     ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_TEMP_READINGS, | 
 | 1499 |                            NULL, getTempReadings, PRIVILEGE_USER); | 
 | 1500 |  | 
| Marri Devender Rao | 66c5fda | 2018-01-18 10:48:37 -0600 | [diff] [blame] | 1501 |     // <Get Power Reading> | 
 | 1502 |     ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_POWER_READING, | 
 | 1503 |                            NULL, getPowerReading, PRIVILEGE_USER); | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 1504 |  | 
 | 1505 |     // <Get Sensor Info> | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1506 |     ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_SENSOR_INFO, NULL, | 
 | 1507 |                            getSensorInfo, PRIVILEGE_USER); | 
| Deepak Kodihalli | 0b45955 | 2018-02-06 06:25:12 -0600 | [diff] [blame] | 1508 |  | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1509 |     // <Get DCMI Configuration Parameters> | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1510 |     ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_CONF_PARAMS, NULL, | 
 | 1511 |                            getDCMIConfParams, PRIVILEGE_USER); | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1512 |  | 
 | 1513 |     // <Set DCMI Configuration Parameters> | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 1514 |     ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::SET_CONF_PARAMS, NULL, | 
 | 1515 |                            setDCMIConfParams, PRIVILEGE_ADMIN); | 
| Nagaraju Goruganti | 22be97b | 2018-02-07 01:19:59 -0600 | [diff] [blame] | 1516 |  | 
| Chris Austen | 1810bec | 2015-10-13 12:12:39 -0500 | [diff] [blame] | 1517 |     return; | 
 | 1518 | } | 
| Tom | 0573237 | 2016-09-06 17:21:23 +0530 | [diff] [blame] | 1519 | // 956379 |