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