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