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