1 #pragma once
2 
3 #include <ipmid/types.hpp>
4 #include <sdbusplus/server.hpp>
5 
6 #include <chrono>
7 #include <cstdint>
8 #include <iomanip>
9 #include <iostream>
10 #include <sstream>
11 
12 namespace ipmi
13 {
14 
15 namespace sel
16 {
17 
18 static constexpr auto mapperBusName = "xyz.openbmc_project.ObjectMapper";
19 static constexpr auto mapperObjPath = "/xyz/openbmc_project/object_mapper";
20 static constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper";
21 
22 static constexpr auto logWatchPath = "/xyz/openbmc_project/logging";
23 static constexpr auto logBasePath = "/xyz/openbmc_project/logging/entry";
24 static constexpr auto logEntryIntf = "xyz.openbmc_project.Logging.Entry";
25 static constexpr auto logDeleteIntf = "xyz.openbmc_project.Object.Delete";
26 
27 static constexpr auto logObj = "/xyz/openbmc_project/logging";
28 static constexpr auto logIntf = "xyz.openbmc_project.Collection.DeleteAll";
29 static constexpr auto logDeleteAllMethod = "DeleteAll";
30 
31 static constexpr auto propIntf = "org.freedesktop.DBus.Properties";
32 
33 using ObjectPaths = std::vector<std::string>;
34 using PropertyName = std::string;
35 using Resolved = bool;
36 using Id = uint32_t;
37 using Timestamp = uint64_t;
38 using Message = std::string;
39 using AdditionalData = std::vector<std::string>;
40 using PropertyType =
41     std::variant<Resolved, Id, Timestamp, Message, AdditionalData>;
42 
43 static constexpr auto selVersion = 0x51;
44 static constexpr auto invalidTimeStamp = 0xFFFFFFFF;
45 
46 static constexpr auto firstEntry = 0x0000;
47 static constexpr auto lastEntry = 0xFFFF;
48 static constexpr auto entireRecord = 0xFF;
49 static constexpr auto selRecordSize = 16;
50 
51 namespace operationSupport
52 {
53 static constexpr bool overflow = false;
54 static constexpr bool deleteSel = true;
55 static constexpr bool partialAddSelEntry = false;
56 static constexpr bool reserveSel = true;
57 static constexpr bool getSelAllocationInfo = false;
58 } // namespace operationSupport
59 
60 /** @struct GetSELEntryRequest
61  *
62  *  IPMI payload for Get SEL Entry command request.
63  */
64 struct GetSELEntryRequest
65 {
66     uint16_t reservationID; //!< Reservation ID.
67     uint16_t selRecordID;   //!< SEL Record ID.
68     uint8_t offset;         //!< Offset into record.
69     uint8_t readLength;     //!< Bytes to read.
70 } __attribute__((packed));
71 
72 constexpr size_t SELRecordLength = 16;
73 
74 /** @struct SELEventRecord
75  *
76  * IPMI SEL Event Record
77  */
78 struct SELEventRecord
79 {
80     uint16_t recordID;        //!< Record ID.
81     uint8_t recordType;       //!< Record Type.
82     uint32_t timeStamp;       //!< Timestamp.
83     uint16_t generatorID;     //!< Generator ID.
84     uint8_t eventMsgRevision; //!< Event Message Revision.
85     uint8_t sensorType;       //!< Sensor Type.
86     uint8_t sensorNum;        //!< Sensor Number.
87     uint8_t eventType;        //!< Event Dir | Event Type.
88     uint8_t eventData1;       //!< Event Data 1.
89     uint8_t eventData2;       //!< Event Data 2.
90     uint8_t eventData3;       //!< Event Data 3.
91 } __attribute__((packed));
92 
93 static_assert(sizeof(SELEventRecord) == SELRecordLength);
94 
95 /** @struct SELOEMRecordTypeCD
96  *
97  * IPMI SEL OEM Record - Type C0h-DFh
98  */
99 struct SELOEMRecordTypeCD
100 {
101     uint16_t recordID;         //!< Record ID.
102     uint8_t recordType;        //!< Record Type.
103     uint32_t timeStamp;        //!< Timestamp.
104     uint8_t manufacturerID[3]; //!< Manufacturer ID.
105     uint8_t oemDefined[6];     //!< OEM Defined data.
106 } __attribute__((packed));
107 
108 static_assert(sizeof(SELOEMRecordTypeCD) == SELRecordLength);
109 
110 /** @struct SELOEMRecordTypeEF
111  *
112  * IPMI SEL OEM Record - Type E0h-FFh
113  */
114 struct SELOEMRecordTypeEF
115 {
116     uint16_t recordID;      //!< Record ID.
117     uint8_t recordType;     //!< Record Type.
118     uint8_t oemDefined[13]; //!< OEM Defined data.
119 } __attribute__((packed));
120 
121 static_assert(sizeof(SELOEMRecordTypeEF) == SELRecordLength);
122 
123 union SELEventRecordFormat
124 {
125     SELEventRecord eventRecord;
126     SELOEMRecordTypeCD oemCD;
127     SELOEMRecordTypeEF oemEF;
128 };
129 
130 /** @struct GetSELEntryResponse
131  *
132  *  IPMI payload for Get SEL Entry command response.
133  */
134 struct GetSELEntryResponse
135 {
136     uint16_t nextRecordID;      //!< Next RecordID.
137     SELEventRecordFormat event; // !< The Event Record.
138 } __attribute__((packed));
139 
140 static_assert(sizeof(GetSELEntryResponse) ==
141               SELRecordLength + sizeof(uint16_t));
142 
143 static constexpr auto initiateErase = 0xAA;
144 static constexpr auto getEraseStatus = 0x00;
145 static constexpr auto eraseComplete = 0x01;
146 
147 /** @brief Convert logging entry to SEL
148  *
149  *  @param[in] objPath - DBUS object path of the logging entry.
150  *
151  *  @return On success return the response of Get SEL entry command.
152  */
153 GetSELEntryResponse convertLogEntrytoSEL(const std::string& objPath);
154 
155 /** @brief Get the timestamp of the log entry
156  *
157  *  @param[in] objPath - DBUS object path of the logging entry.
158  *
159  *  @return On success return the timestamp of the log entry as number of
160  *          seconds from epoch.
161  */
162 std::chrono::seconds getEntryTimeStamp(const std::string& objPath);
163 
164 /** @brief Read the logging entry object paths
165  *
166  *  This API would read the logging dbus logging entry object paths and sorting
167  *  the filename in the numeric order. The paths is cleared before populating
168  *  the object paths.
169  *
170  *  @param[in,out] paths - sorted list of logging entry object paths.
171  *
172  *  @note This function is invoked when the Get SEL Info command or the Delete
173  *        SEL entry command is invoked. The Get SEL Entry command is preceded
174  *        typically by Get SEL Info command, so readLoggingObjectPaths is not
175  *        invoked before each Get SEL entry command.
176  */
177 void readLoggingObjectPaths(ObjectPaths& paths);
178 
179 template <typename T>
toHexStr(const T & data)180 std::string toHexStr(const T& data)
181 {
182     std::stringstream stream;
183     stream << std::hex << std::uppercase << std::setfill('0');
184     for (const auto& v : data)
185     {
186         stream << std::setw(2) << static_cast<int>(v);
187     }
188     return stream.str();
189 }
190 namespace internal
191 {
192 
193 /** @brief Convert logging entry to SEL event record
194  *
195  *  @param[in] objPath - DBUS object path of the logging entry.
196  *  @param[in] iter - Iterator to the sensor data corresponding to the logging
197  *                    entry
198  *
199  *  @return On success return the SEL event record, throw an exception in case
200  *          of failure.
201  */
202 GetSELEntryResponse
203     prepareSELEntry(const std::string& objPath,
204                     ipmi::sensor::InvObjectIDMap::const_iterator iter);
205 
206 } // namespace internal
207 
208 } // namespace sel
209 
210 } // namespace ipmi
211