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