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