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