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