1 #ifndef __HOST_IPMI_DCMI_HANDLER_H__ 2 #define __HOST_IPMI_DCMI_HANDLER_H__ 3 4 #include <map> 5 #include <string> 6 #include <vector> 7 #include <sdbusplus/bus.hpp> 8 #include "nlohmann/json.hpp" 9 10 namespace dcmi 11 { 12 13 using NumInstances = size_t; 14 using Json = nlohmann::json; 15 16 enum Commands 17 { 18 // Get capability bits 19 GET_CAPABILITIES = 0x01, 20 GET_POWER_READING = 0x02, 21 GET_POWER_LIMIT = 0x03, 22 SET_POWER_LIMIT = 0x04, 23 APPLY_POWER_LIMIT = 0x05, 24 GET_ASSET_TAG = 0x06, 25 GET_SENSOR_INFO = 0x07, 26 SET_ASSET_TAG = 0x08, 27 GET_MGMNT_CTRL_ID_STR = 0x09, 28 SET_MGMNT_CTRL_ID_STR = 0x0A, 29 GET_TEMP_READINGS = 0x10, 30 SET_CONF_PARAMS = 0x12, 31 GET_CONF_PARAMS = 0x13, 32 }; 33 34 static constexpr auto propIntf = "org.freedesktop.DBus.Properties"; 35 static constexpr auto assetTagIntf = 36 "xyz.openbmc_project.Inventory.Decorator.AssetTag"; 37 static constexpr auto assetTagProp = "AssetTag"; 38 static constexpr auto networkServiceName = "xyz.openbmc_project.Network"; 39 static constexpr auto networkConfigObj = 40 "/xyz/openbmc_project/network/config"; 41 static constexpr auto networkConfigIntf = 42 "xyz.openbmc_project.Network.SystemConfiguration"; 43 static constexpr auto hostNameProp = "HostName"; 44 static constexpr auto temperatureSensorType = 0x01; 45 static constexpr auto maxInstances = 255; 46 static constexpr auto configFile = 47 "/usr/share/ipmi-providers/dcmi_sensors.json"; 48 static constexpr auto ethernetIntf = 49 "xyz.openbmc_project.Network.EthernetInterface"; 50 static constexpr auto ethernetDefaultChannelNum = 0x1; 51 static constexpr auto networkRoot = "/xyz/openbmc_project/network"; 52 static constexpr auto dhcpObj = "/xyz/openbmc_project/network/config/dhcp"; 53 static constexpr auto dhcpIntf = 54 "xyz.openbmc_project.Network.DHCPConfiguration"; 55 static constexpr auto systemBusName = "org.freedesktop.systemd1"; 56 static constexpr auto systemPath = "/org/freedesktop/systemd1"; 57 static constexpr auto systemIntf = "org.freedesktop.systemd1.Manager"; 58 59 namespace assettag 60 { 61 62 using ObjectPath = std::string; 63 using Service = std::string; 64 using Interfaces = std::vector<std::string>; 65 using ObjectTree = std::map<ObjectPath, std::map<Service, Interfaces>>; 66 67 } //namespace assettag 68 69 namespace temp_readings 70 { 71 static constexpr auto maxDataSets = 8; 72 static constexpr auto maxTemp = 127; // degrees C 73 74 /** @struct Response 75 * 76 * DCMI payload for Get Temperature Readings response 77 */ 78 struct Response 79 { 80 #if BYTE_ORDER == LITTLE_ENDIAN 81 uint8_t temperature: 7; //!< Temperature reading in Celsius 82 uint8_t sign: 1; //!< Sign bit 83 #endif 84 #if BYTE_ORDER == BIG_ENDIAN 85 uint8_t sign: 1; //!< Sign bit 86 uint8_t temperature: 7; //!< Temperature reading in Celsius 87 #endif 88 uint8_t instance; //!< Entity instance number 89 } __attribute__((packed)); 90 91 using ResponseList = std::vector<Response>; 92 using Value = uint8_t; 93 using Sign = bool; 94 using Temperature = std::tuple<Value, Sign>; 95 } 96 97 namespace sensor_info 98 { 99 static constexpr auto maxRecords = 8; 100 101 /** @struct Response 102 * 103 * DCMI payload for Get Sensor Info response 104 */ 105 struct Response 106 { 107 uint8_t recordIdLsb; //!< SDR record id LS byte 108 uint8_t recordIdMsb; //!< SDR record id MS byte 109 } __attribute__((packed)); 110 111 using ResponseList = std::vector<Response>; 112 } // namespace sensor_info 113 114 static constexpr auto groupExtId = 0xDC; 115 116 static constexpr auto assetTagMaxOffset = 62; 117 static constexpr auto assetTagMaxSize = 63; 118 static constexpr auto maxBytes = 16; 119 static constexpr size_t maxCtrlIdStrLen = 63; 120 121 /** @struct GetAssetTagRequest 122 * 123 * DCMI payload for Get Asset Tag command request. 124 */ 125 struct GetAssetTagRequest 126 { 127 uint8_t groupID; //!< Group extension identification. 128 uint8_t offset; //!< Offset to read. 129 uint8_t bytes; //!< Number of bytes to read. 130 } __attribute__((packed)); 131 132 /** @struct GetAssetTagResponse 133 * 134 * DCMI payload for Get Asset Tag command response. 135 */ 136 struct GetAssetTagResponse 137 { 138 uint8_t groupID; //!< Group extension identification. 139 uint8_t tagLength; //!< Total asset tag length. 140 } __attribute__((packed)); 141 142 /** @struct SetAssetTagRequest 143 * 144 * DCMI payload for Set Asset Tag command request. 145 */ 146 struct SetAssetTagRequest 147 { 148 uint8_t groupID; //!< Group extension identification. 149 uint8_t offset; //!< Offset to write. 150 uint8_t bytes; //!< Number of bytes to write. 151 } __attribute__((packed)); 152 153 /** @struct SetAssetTagResponse 154 * 155 * DCMI payload for Set Asset Tag command response. 156 */ 157 struct SetAssetTagResponse 158 { 159 uint8_t groupID; //!< Group extension identification. 160 uint8_t tagLength; //!< Total asset tag length. 161 } __attribute__((packed)); 162 163 /** @brief Read the object tree to fetch the object path that implemented the 164 * Asset tag interface. 165 * 166 * @param[in,out] objectTree - object tree 167 * 168 * @return On success return the object tree with the object path that 169 * implemented the AssetTag interface. 170 */ 171 void readAssetTagObjectTree(dcmi::assettag::ObjectTree& objectTree); 172 173 /** @brief Read the asset tag of the server 174 * 175 * @return On success return the asset tag. 176 */ 177 std::string readAssetTag(); 178 179 /** @brief Write the asset tag to the asset tag DBUS property 180 * 181 * @param[in] assetTag - Asset Tag to be written to the property. 182 */ 183 void writeAssetTag(const std::string& assetTag); 184 185 /** @brief Read the current power cap value 186 * 187 * @param[in] bus - dbus connection 188 * 189 * @return On success return the power cap value. 190 */ 191 uint32_t getPcap(sdbusplus::bus::bus& bus); 192 193 /** @brief Check if the power capping is enabled 194 * 195 * @param[in] bus - dbus connection 196 * 197 * @return true if the powerCap is enabled and false if the powercap 198 * is disabled. 199 */ 200 bool getPcapEnabled(sdbusplus::bus::bus& bus); 201 202 /** @struct GetPowerLimitRequest 203 * 204 * DCMI payload for Get Power Limit command request. 205 */ 206 struct GetPowerLimitRequest 207 { 208 uint8_t groupID; //!< Group extension identification. 209 uint16_t reserved; //!< Reserved 210 } __attribute__((packed)); 211 212 /** @struct GetPowerLimitResponse 213 * 214 * DCMI payload for Get Power Limit command response. 215 */ 216 struct GetPowerLimitResponse 217 { 218 uint8_t groupID; //!< Group extension identification. 219 uint16_t reserved; //!< Reserved. 220 uint8_t exceptionAction; //!< Exception action. 221 uint16_t powerLimit; //!< Power limit requested in watts. 222 uint32_t correctionTime; //!< Correction time limit in milliseconds. 223 uint16_t reserved1; //!< Reserved. 224 uint16_t samplingPeriod; //!< Statistics sampling period in seconds. 225 } __attribute__((packed)); 226 227 /** @brief Set the power cap value 228 * 229 * @param[in] bus - dbus connection 230 * @param[in] powerCap - power cap value 231 */ 232 void setPcap(sdbusplus::bus::bus& bus, const uint32_t powerCap); 233 234 /** @struct SetPowerLimitRequest 235 * 236 * DCMI payload for Set Power Limit command request. 237 */ 238 struct SetPowerLimitRequest 239 { 240 uint8_t groupID; //!< Group extension identification. 241 uint16_t reserved; //!< Reserved 242 uint8_t reserved1; //!< Reserved 243 uint8_t exceptionAction; //!< Exception action. 244 uint16_t powerLimit; //!< Power limit requested in watts. 245 uint32_t correctionTime; //!< Correction time limit in milliseconds. 246 uint16_t reserved2; //!< Reserved. 247 uint16_t samplingPeriod; //!< Statistics sampling period in seconds. 248 } __attribute__((packed)); 249 250 /** @struct SetPowerLimitResponse 251 * 252 * DCMI payload for Set Power Limit command response. 253 */ 254 struct SetPowerLimitResponse 255 { 256 uint8_t groupID; //!< Group extension identification. 257 } __attribute__((packed)); 258 259 /** @brief Enable or disable the power capping 260 * 261 * @param[in] bus - dbus connection 262 * @param[in] enabled - enable/disable 263 */ 264 void setPcapEnable(sdbusplus::bus::bus& bus, bool enabled); 265 266 /** @struct ApplyPowerLimitRequest 267 * 268 * DCMI payload for Activate/Deactivate Power Limit command request. 269 */ 270 struct ApplyPowerLimitRequest 271 { 272 uint8_t groupID; //!< Group extension identification. 273 uint8_t powerLimitAction; //!< Power limit activation 274 uint16_t reserved; //!< Reserved 275 } __attribute__((packed)); 276 277 /** @struct ApplyPowerLimitResponse 278 * 279 * DCMI payload for Acticate/Deactivate Power Limit command response. 280 */ 281 struct ApplyPowerLimitResponse 282 { 283 uint8_t groupID; //!< Group extension identification. 284 } __attribute__((packed)); 285 286 /** @struct GetMgmntCtrlIdStrRequest 287 * 288 * DCMI payload for Get Management Controller Identifier String cmd request. 289 */ 290 struct GetMgmntCtrlIdStrRequest 291 { 292 uint8_t groupID; //!< Group extension identification. 293 uint8_t offset; //!< Offset to read. 294 uint8_t bytes; //!< Number of bytes to read. 295 } __attribute__((packed)); 296 297 /** @struct GetMgmntCtrlIdStrResponse 298 * 299 * DCMI payload for Get Management Controller Identifier String cmd response. 300 */ 301 struct GetMgmntCtrlIdStrResponse 302 { 303 uint8_t groupID; //!< Group extension identification. 304 uint8_t strLen; //!< ID string length. 305 char data[]; //!< ID string 306 } __attribute__((packed)); 307 308 /** @struct SetMgmntCtrlIdStrRequest 309 * 310 * DCMI payload for Set Management Controller Identifier String cmd request. 311 */ 312 struct SetMgmntCtrlIdStrRequest 313 { 314 uint8_t groupID; //!< Group extension identification. 315 uint8_t offset; //!< Offset to write. 316 uint8_t bytes; //!< Number of bytes to read. 317 char data[]; //!< ID string 318 } __attribute__((packed)); 319 320 /** @struct GetMgmntCtrlIdStrResponse 321 * 322 * DCMI payload for Get Management Controller Identifier String cmd response. 323 */ 324 struct SetMgmntCtrlIdStrResponse 325 { 326 uint8_t groupID; //!< Group extension identification. 327 uint8_t offset; //!< Last Offset Written. 328 } __attribute__((packed)); 329 330 /** @enum DCMICapParameters 331 * 332 * DCMI Capability parameters 333 */ 334 enum class DCMICapParameters 335 { 336 SUPPORTED_DCMI_CAPS = 0x01, //!< Supported DCMI Capabilities 337 MANDATORY_PLAT_ATTRIBUTES = 0x02, //!< Mandatory Platform Attributes 338 OPTIONAL_PLAT_ATTRIBUTES = 0x03, //!< Optional Platform Attributes 339 MANAGEABILITY_ACCESS_ATTRIBUTES = 0x04, //!< Manageability Access Attributes 340 }; 341 342 /** @struct GetDCMICapRequest 343 * 344 * DCMI payload for Get capabilities cmd request. 345 */ 346 struct GetDCMICapRequest 347 { 348 uint8_t groupID; //!< Group extension identification. 349 uint8_t param; //!< Capability parameter selector. 350 } __attribute__((packed)); 351 352 /** @struct GetDCMICapRequest 353 * 354 * DCMI payload for Get capabilities cmd response. 355 */ 356 struct GetDCMICapResponse 357 { 358 uint8_t groupID; //!< Group extension identification. 359 uint8_t major; //!< DCMI Specification Conformance - major ver 360 uint8_t minor; //!< DCMI Specification Conformance - minor ver 361 uint8_t paramRevision; //!< Parameter Revision = 02h 362 uint8_t data[]; //!< Capability array 363 } __attribute__((packed)); 364 365 /** @struct DCMICap 366 * 367 * DCMI capabilities protocol info. 368 */ 369 struct DCMICap 370 { 371 std::string name; //!< Name of DCMI capability. 372 uint8_t bytePosition; //!< Starting byte number from DCMI spec. 373 uint8_t position; //!< bit position from the DCMI spec. 374 uint8_t length; //!< Length of the value from DCMI spec. 375 }; 376 377 using DCMICapList = std::vector<DCMICap>; 378 379 /** @struct DCMICapEntry 380 * 381 * DCMI capabilities list and size for each parameter. 382 */ 383 struct DCMICapEntry 384 { 385 uint8_t size; //!< Size of capability array in bytes. 386 DCMICapList capList; //!< List of capabilities for a parameter. 387 }; 388 389 using DCMICaps = std::map<DCMICapParameters, DCMICapEntry>; 390 391 /** @struct GetTempReadingsRequest 392 * 393 * DCMI payload for Get Temperature Readings request 394 */ 395 struct GetTempReadingsRequest 396 { 397 uint8_t groupID; //!< Group extension identification. 398 uint8_t sensorType; //!< Type of the sensor 399 uint8_t entityId; //!< Entity ID 400 uint8_t entityInstance; //!< Entity Instance (0 means all instances) 401 uint8_t instanceStart; //!< Instance start (used if instance is 0) 402 } __attribute__((packed)); 403 404 /** @struct GetTempReadingsResponse 405 * 406 * DCMI header for Get Temperature Readings response 407 */ 408 struct GetTempReadingsResponseHdr 409 { 410 uint8_t groupID; //!< Group extension identification. 411 uint8_t numInstances; //!< No. of instances for requested id 412 uint8_t numDataSets; //!< No. of sets of temperature data 413 } __attribute__((packed)); 414 415 /** @brief Parse out JSON config file containing information 416 * related to sensors. 417 * 418 * @return A json object 419 */ 420 Json parseSensorConfig(); 421 422 namespace temp_readings 423 { 424 /** @brief Read temperature from a d-bus object, scale it as per dcmi 425 * get temperature reading requirements. 426 * 427 * @param[in] dbusService - the D-Bus service 428 * @param[in] dbusPath - the D-Bus path 429 * 430 * @return A temperature reading 431 */ 432 Temperature readTemp(const std::string& dbusService, 433 const std::string& dbusPath); 434 435 /** @brief Read temperatures and fill up DCMI response for the Get 436 * Temperature Readings command. This looks at a specific 437 * instance. 438 * 439 * @param[in] type - one of "inlet", "cpu", "baseboard" 440 * @param[in] instance - A non-zero Entity instance number 441 * 442 * @return A tuple, containing a temperature reading and the 443 * number of instances. 444 */ 445 std::tuple<Response, NumInstances> read (const std::string& type, 446 uint8_t instance); 447 448 /** @brief Read temperatures and fill up DCMI response for the Get 449 * Temperature Readings command. This looks at a range of 450 * instances. 451 * 452 * @param[in] type - one of "inlet", "cpu", "baseboard" 453 * @param[in] instanceStart - Entity instance start index 454 * 455 * @return A tuple, containing a list of temperature readings and the 456 * number of instances. 457 */ 458 std::tuple<ResponseList, NumInstances> readAll(const std::string& type, 459 uint8_t instanceStart); 460 } 461 462 namespace sensor_info 463 { 464 /** @brief Create response from JSON config. 465 * 466 * @param[in] config - JSON config info about DCMI sensors 467 * 468 * @return Sensor info response 469 */ 470 Response createFromJson(const Json& config); 471 472 /** @brief Read sensor info and fill up DCMI response for the Get 473 * Sensor Info command. This looks at a specific 474 * instance. 475 * 476 * @param[in] type - one of "inlet", "cpu", "baseboard" 477 * @param[in] instance - A non-zero Entity instance number 478 * @param[in] config - JSON config info about DCMI sensors 479 * 480 * @return A tuple, containing a sensor info response and 481 * number of instances. 482 */ 483 std::tuple<Response, NumInstances> read(const std::string& type, 484 uint8_t instance, 485 const Json& config); 486 487 /** @brief Read sensor info and fill up DCMI response for the Get 488 * Sensor Info command. This looks at a range of 489 * instances. 490 * 491 * @param[in] type - one of "inlet", "cpu", "baseboard" 492 * @param[in] instanceStart - Entity instance start index 493 * @param[in] config - JSON config info about DCMI sensors 494 * 495 * @return A tuple, containing a list of sensor info responses and the 496 * number of instances. 497 */ 498 std::tuple<ResponseList, NumInstances> readAll(const std::string& type, 499 uint8_t instanceStart, 500 const Json& config); 501 } // namespace sensor_info 502 503 /** @brief Read power reading from power reading sensor object 504 * 505 * @param[in] bus - dbus connection 506 * 507 * @return total power reading 508 */ 509 int64_t getPowerReading(sdbusplus::bus::bus& bus); 510 511 /** @struct GetPowerReadingRequest 512 * 513 * DCMI Get Power Reading command request. 514 * Refer DCMI specification Version 1.1 Section 6.6.1 515 */ 516 struct GetPowerReadingRequest 517 { 518 uint8_t groupID; //!< Group extension identification. 519 uint8_t mode; //!< Mode 520 uint8_t modeAttribute; //!< Mode Attributes 521 } __attribute__((packed)); 522 523 /** @struct GetPowerReadingResponse 524 * 525 * DCMI Get Power Reading command response. 526 * Refer DCMI specification Version 1.1 Section 6.6.1 527 */ 528 struct GetPowerReadingResponse 529 { 530 uint8_t groupID; //!< Group extension identification. 531 uint16_t currentPower; //!< Current power in watts 532 uint16_t minimumPower; //!< Minimum power over sampling duration 533 //!< in watts 534 uint16_t maximumPower; //!< Maximum power over sampling duration 535 //!< in watts 536 uint16_t averagePower; //!< Average power over sampling duration 537 //!< in watts 538 uint32_t timeStamp; //!< IPMI specification based time stamp 539 uint32_t timeFrame; //!< Statistics reporting time period in milli 540 //!< seconds. 541 uint8_t powerReadingState; //!< Power Reading State 542 } __attribute__((packed)); 543 544 /** @struct GetSensorInfoRequest 545 * 546 * DCMI payload for Get Sensor Info request 547 */ 548 struct GetSensorInfoRequest 549 { 550 uint8_t groupID; //!< Group extension identification. 551 uint8_t sensorType; //!< Type of the sensor 552 uint8_t entityId; //!< Entity ID 553 uint8_t entityInstance; //!< Entity Instance (0 means all instances) 554 uint8_t instanceStart; //!< Instance start (used if instance is 0) 555 } __attribute__((packed)); 556 557 /** @struct GetSensorInfoResponseHdr 558 * 559 * DCMI header for Get Sensor Info response 560 */ 561 struct GetSensorInfoResponseHdr 562 { 563 uint8_t groupID; //!< Group extension identification. 564 uint8_t numInstances; //!< No. of instances for requested id 565 uint8_t numRecords; //!< No. of record ids in the response 566 } __attribute__((packed)); 567 /** 568 * @brief Parameters for DCMI Configuration Parameters 569 */ 570 enum class DCMIConfigParameters: uint8_t 571 { 572 ActivateDHCP = 1, 573 DiscoveryConfig, 574 DHCPTiming1, 575 DHCPTiming2, 576 DHCPTiming3, 577 }; 578 579 /** @struct SetConfParamsRequest 580 * 581 * DCMI Set DCMI Configuration Parameters Command. 582 * Refer DCMI specification Version 1.1 Section 6.1.2 583 */ 584 struct SetConfParamsRequest 585 { 586 uint8_t groupID; //!< Group extension identification. 587 uint8_t paramSelect; //!< Parameter selector. 588 uint8_t setSelect; //!< Set Selector (use 00h for parameters that only 589 //!< have one set). 590 uint8_t data[]; //!< Configuration parameter data. 591 } __attribute__((packed)); 592 593 /** @struct SetConfParamsResponse 594 * 595 * DCMI Set DCMI Configuration Parameters Command response. 596 * Refer DCMI specification Version 1.1 Section 6.1.2 597 */ 598 struct SetConfParamsResponse 599 { 600 uint8_t groupID; //!< Group extension identification. 601 } __attribute__((packed)); 602 603 /** @struct GetConfParamsRequest 604 * 605 * DCMI Get DCMI Configuration Parameters Command. 606 * Refer DCMI specification Version 1.1 Section 6.1.3 607 */ 608 struct GetConfParamsRequest 609 { 610 uint8_t groupID; //!< Group extension identification. 611 uint8_t paramSelect; //!< Parameter selector. 612 uint8_t setSelect; //!< Set Selector. Selects a given set of parameters 613 //!< under a given Parameter selector value. 00h if 614 //!< parameter doesn't use a Set Selector. 615 } __attribute__((packed)); 616 617 /** @struct GetConfParamsResponse 618 * 619 * DCMI Get DCMI Configuration Parameters Command response. 620 * Refer DCMI specification Version 1.1 Section 6.1.3 621 */ 622 struct GetConfParamsResponse 623 { 624 uint8_t groupID; //!< Group extension identification. 625 uint8_t major; //!< DCMI Spec Conformance - major ver = 01h. 626 uint8_t minor; //!< DCMI Spec Conformance - minor ver = 05h. 627 uint8_t paramRevision; //!< Parameter Revision = 01h. 628 uint8_t data[]; //!< Parameter data. 629 630 } __attribute__((packed)); 631 632 } // namespace dcmi 633 634 #endif 635