xref: /openbmc/fb-ipmi-oem/src/selcommands.cpp (revision 11b9c3b1bd22c6719868d3b5589640ab188a24f8)
1*11b9c3b1SVijay Khemka /*
2*11b9c3b1SVijay Khemka  * Copyright (c)  2018 Intel Corporation.
3*11b9c3b1SVijay Khemka  * Copyright (c)  2018-present Facebook.
4*11b9c3b1SVijay Khemka  *
5*11b9c3b1SVijay Khemka  * Licensed under the Apache License, Version 2.0 (the "License");
6*11b9c3b1SVijay Khemka  * you may not use this file except in compliance with the License.
7*11b9c3b1SVijay Khemka  * You may obtain a copy of the License at
8*11b9c3b1SVijay Khemka  *
9*11b9c3b1SVijay Khemka  *      http://www.apache.org/licenses/LICENSE-2.0
10*11b9c3b1SVijay Khemka  *
11*11b9c3b1SVijay Khemka  * Unless required by applicable law or agreed to in writing, software
12*11b9c3b1SVijay Khemka  * distributed under the License is distributed on an "AS IS" BASIS,
13*11b9c3b1SVijay Khemka  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*11b9c3b1SVijay Khemka  * See the License for the specific language governing permissions and
15*11b9c3b1SVijay Khemka  * limitations under the License.
16*11b9c3b1SVijay Khemka  */
17*11b9c3b1SVijay Khemka 
18*11b9c3b1SVijay Khemka #include <ipmid/api.hpp>
19*11b9c3b1SVijay Khemka 
20*11b9c3b1SVijay Khemka #include <boost/algorithm/string/join.hpp>
21*11b9c3b1SVijay Khemka #include <nlohmann/json.hpp>
22*11b9c3b1SVijay Khemka #include <iostream>
23*11b9c3b1SVijay Khemka #include <sstream>
24*11b9c3b1SVijay Khemka #include <fstream>
25*11b9c3b1SVijay Khemka #include <phosphor-logging/log.hpp>
26*11b9c3b1SVijay Khemka #include <sdbusplus/message/types.hpp>
27*11b9c3b1SVijay Khemka #include <sdbusplus/timer.hpp>
28*11b9c3b1SVijay Khemka #include <storagecommands.hpp>
29*11b9c3b1SVijay Khemka 
30*11b9c3b1SVijay Khemka //----------------------------------------------------------------------
31*11b9c3b1SVijay Khemka // Platform specific functions for storing app data
32*11b9c3b1SVijay Khemka //----------------------------------------------------------------------
33*11b9c3b1SVijay Khemka 
34*11b9c3b1SVijay Khemka static void toHexStr(std::vector<uint8_t> &bytes, std::string &hexStr)
35*11b9c3b1SVijay Khemka {
36*11b9c3b1SVijay Khemka     std::stringstream stream;
37*11b9c3b1SVijay Khemka     stream << std::hex << std::uppercase << std::setfill('0');
38*11b9c3b1SVijay Khemka     for (const uint8_t byte : bytes)
39*11b9c3b1SVijay Khemka     {
40*11b9c3b1SVijay Khemka         stream << std::setw(2) << static_cast<int>(byte);
41*11b9c3b1SVijay Khemka     }
42*11b9c3b1SVijay Khemka     hexStr = stream.str();
43*11b9c3b1SVijay Khemka }
44*11b9c3b1SVijay Khemka 
45*11b9c3b1SVijay Khemka static int fromHexStr(const std::string hexStr, std::vector<uint8_t> &data)
46*11b9c3b1SVijay Khemka {
47*11b9c3b1SVijay Khemka     for (unsigned int i = 0; i < hexStr.size(); i += 2)
48*11b9c3b1SVijay Khemka     {
49*11b9c3b1SVijay Khemka         try
50*11b9c3b1SVijay Khemka         {
51*11b9c3b1SVijay Khemka             data.push_back(static_cast<uint8_t>(
52*11b9c3b1SVijay Khemka                 std::stoul(hexStr.substr(i, 2), nullptr, 16)));
53*11b9c3b1SVijay Khemka         }
54*11b9c3b1SVijay Khemka         catch (std::invalid_argument &e)
55*11b9c3b1SVijay Khemka         {
56*11b9c3b1SVijay Khemka             phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
57*11b9c3b1SVijay Khemka             return -1;
58*11b9c3b1SVijay Khemka         }
59*11b9c3b1SVijay Khemka         catch (std::out_of_range &e)
60*11b9c3b1SVijay Khemka         {
61*11b9c3b1SVijay Khemka             phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
62*11b9c3b1SVijay Khemka             return -1;
63*11b9c3b1SVijay Khemka         }
64*11b9c3b1SVijay Khemka     }
65*11b9c3b1SVijay Khemka     return 0;
66*11b9c3b1SVijay Khemka }
67*11b9c3b1SVijay Khemka 
68*11b9c3b1SVijay Khemka namespace fb_oem::ipmi::sel
69*11b9c3b1SVijay Khemka {
70*11b9c3b1SVijay Khemka 
71*11b9c3b1SVijay Khemka class SELData
72*11b9c3b1SVijay Khemka {
73*11b9c3b1SVijay Khemka   private:
74*11b9c3b1SVijay Khemka     nlohmann::json selDataObj;
75*11b9c3b1SVijay Khemka 
76*11b9c3b1SVijay Khemka     void flush()
77*11b9c3b1SVijay Khemka     {
78*11b9c3b1SVijay Khemka         std::ofstream file(SEL_JSON_DATA_FILE);
79*11b9c3b1SVijay Khemka         file << selDataObj;
80*11b9c3b1SVijay Khemka         file.close();
81*11b9c3b1SVijay Khemka     }
82*11b9c3b1SVijay Khemka 
83*11b9c3b1SVijay Khemka     void init()
84*11b9c3b1SVijay Khemka     {
85*11b9c3b1SVijay Khemka         selDataObj[KEY_SEL_VER] = 0x51;
86*11b9c3b1SVijay Khemka         selDataObj[KEY_SEL_COUNT] = 0;
87*11b9c3b1SVijay Khemka         selDataObj[KEY_ADD_TIME] = 0xFFFFFFFF;
88*11b9c3b1SVijay Khemka         selDataObj[KEY_ERASE_TIME] = 0xFFFFFFFF;
89*11b9c3b1SVijay Khemka         selDataObj[KEY_OPER_SUPP] = 0x02;
90*11b9c3b1SVijay Khemka         /* Spec indicates that more than 64kB is free */
91*11b9c3b1SVijay Khemka         selDataObj[KEY_FREE_SPACE] = 0xFFFF;
92*11b9c3b1SVijay Khemka     }
93*11b9c3b1SVijay Khemka 
94*11b9c3b1SVijay Khemka   public:
95*11b9c3b1SVijay Khemka     SELData()
96*11b9c3b1SVijay Khemka     {
97*11b9c3b1SVijay Khemka         /* Get App data stored in json file */
98*11b9c3b1SVijay Khemka         std::ifstream file(SEL_JSON_DATA_FILE);
99*11b9c3b1SVijay Khemka         if (file)
100*11b9c3b1SVijay Khemka         {
101*11b9c3b1SVijay Khemka             file >> selDataObj;
102*11b9c3b1SVijay Khemka             file.close();
103*11b9c3b1SVijay Khemka         }
104*11b9c3b1SVijay Khemka 
105*11b9c3b1SVijay Khemka         /* Initialize SelData object if no entries. */
106*11b9c3b1SVijay Khemka         if (selDataObj.find(KEY_SEL_COUNT) == selDataObj.end())
107*11b9c3b1SVijay Khemka         {
108*11b9c3b1SVijay Khemka             init();
109*11b9c3b1SVijay Khemka         }
110*11b9c3b1SVijay Khemka     }
111*11b9c3b1SVijay Khemka 
112*11b9c3b1SVijay Khemka     int clear()
113*11b9c3b1SVijay Khemka     {
114*11b9c3b1SVijay Khemka         /* Clear the complete Sel Json object */
115*11b9c3b1SVijay Khemka         selDataObj.clear();
116*11b9c3b1SVijay Khemka         /* Reinitialize it with basic data */
117*11b9c3b1SVijay Khemka         init();
118*11b9c3b1SVijay Khemka         /* Save the erase time */
119*11b9c3b1SVijay Khemka         struct timespec selTime = {};
120*11b9c3b1SVijay Khemka         if (clock_gettime(CLOCK_REALTIME, &selTime) < 0)
121*11b9c3b1SVijay Khemka         {
122*11b9c3b1SVijay Khemka             return -1;
123*11b9c3b1SVijay Khemka         }
124*11b9c3b1SVijay Khemka         selDataObj[KEY_ERASE_TIME] = selTime.tv_sec;
125*11b9c3b1SVijay Khemka         flush();
126*11b9c3b1SVijay Khemka         return 0;
127*11b9c3b1SVijay Khemka     }
128*11b9c3b1SVijay Khemka 
129*11b9c3b1SVijay Khemka     uint32_t getCount()
130*11b9c3b1SVijay Khemka     {
131*11b9c3b1SVijay Khemka         return selDataObj[KEY_SEL_COUNT];
132*11b9c3b1SVijay Khemka     }
133*11b9c3b1SVijay Khemka 
134*11b9c3b1SVijay Khemka     void getInfo(GetSELInfoData &info)
135*11b9c3b1SVijay Khemka     {
136*11b9c3b1SVijay Khemka         info.selVersion = selDataObj[KEY_SEL_VER];
137*11b9c3b1SVijay Khemka         info.entries = selDataObj[KEY_SEL_COUNT];
138*11b9c3b1SVijay Khemka         info.freeSpace = selDataObj[KEY_FREE_SPACE];
139*11b9c3b1SVijay Khemka         info.addTimeStamp = selDataObj[KEY_ADD_TIME];
140*11b9c3b1SVijay Khemka         info.eraseTimeStamp = selDataObj[KEY_ERASE_TIME];
141*11b9c3b1SVijay Khemka         info.operationSupport = selDataObj[KEY_OPER_SUPP];
142*11b9c3b1SVijay Khemka     }
143*11b9c3b1SVijay Khemka 
144*11b9c3b1SVijay Khemka     int getEntry(uint32_t index, std::string &rawStr)
145*11b9c3b1SVijay Khemka     {
146*11b9c3b1SVijay Khemka         std::stringstream ss;
147*11b9c3b1SVijay Khemka         ss << std::hex;
148*11b9c3b1SVijay Khemka         ss << std::setw(2) << std::setfill('0') << index;
149*11b9c3b1SVijay Khemka 
150*11b9c3b1SVijay Khemka         /* Check or the requested SEL Entry, if record is available */
151*11b9c3b1SVijay Khemka         if (selDataObj.find(ss.str()) == selDataObj.end())
152*11b9c3b1SVijay Khemka         {
153*11b9c3b1SVijay Khemka             return -1;
154*11b9c3b1SVijay Khemka         }
155*11b9c3b1SVijay Khemka 
156*11b9c3b1SVijay Khemka         rawStr = selDataObj[ss.str()][KEY_SEL_ENTRY_RAW];
157*11b9c3b1SVijay Khemka         return 0;
158*11b9c3b1SVijay Khemka     }
159*11b9c3b1SVijay Khemka 
160*11b9c3b1SVijay Khemka     int addEntry(std::string keyStr)
161*11b9c3b1SVijay Khemka     {
162*11b9c3b1SVijay Khemka         struct timespec selTime = {};
163*11b9c3b1SVijay Khemka 
164*11b9c3b1SVijay Khemka         if (clock_gettime(CLOCK_REALTIME, &selTime) < 0)
165*11b9c3b1SVijay Khemka         {
166*11b9c3b1SVijay Khemka             return -1;
167*11b9c3b1SVijay Khemka         }
168*11b9c3b1SVijay Khemka 
169*11b9c3b1SVijay Khemka         selDataObj[KEY_ADD_TIME] = selTime.tv_sec;
170*11b9c3b1SVijay Khemka 
171*11b9c3b1SVijay Khemka         int selCount = selDataObj[KEY_SEL_COUNT];
172*11b9c3b1SVijay Khemka         selDataObj[KEY_SEL_COUNT] = ++selCount;
173*11b9c3b1SVijay Khemka 
174*11b9c3b1SVijay Khemka         std::stringstream ss;
175*11b9c3b1SVijay Khemka         ss << std::hex;
176*11b9c3b1SVijay Khemka         ss << std::setw(2) << std::setfill('0') << selCount;
177*11b9c3b1SVijay Khemka 
178*11b9c3b1SVijay Khemka         selDataObj[ss.str()][KEY_SEL_ENTRY_RAW] = keyStr;
179*11b9c3b1SVijay Khemka         flush();
180*11b9c3b1SVijay Khemka         return selCount;
181*11b9c3b1SVijay Khemka     }
182*11b9c3b1SVijay Khemka };
183*11b9c3b1SVijay Khemka 
184*11b9c3b1SVijay Khemka } // namespace fb_oem::ipmi::sel
185*11b9c3b1SVijay Khemka 
186*11b9c3b1SVijay Khemka namespace ipmi
187*11b9c3b1SVijay Khemka {
188*11b9c3b1SVijay Khemka 
189*11b9c3b1SVijay Khemka namespace storage
190*11b9c3b1SVijay Khemka {
191*11b9c3b1SVijay Khemka 
192*11b9c3b1SVijay Khemka static void registerSELFunctions() __attribute__((constructor));
193*11b9c3b1SVijay Khemka static fb_oem::ipmi::sel::SELData selObj __attribute__((init_priority(101)));
194*11b9c3b1SVijay Khemka 
195*11b9c3b1SVijay Khemka ipmi::RspType<uint8_t,  // SEL version
196*11b9c3b1SVijay Khemka               uint16_t, // SEL entry count
197*11b9c3b1SVijay Khemka               uint16_t, // free space
198*11b9c3b1SVijay Khemka               uint32_t, // last add timestamp
199*11b9c3b1SVijay Khemka               uint32_t, // last erase timestamp
200*11b9c3b1SVijay Khemka               uint8_t>  // operation support
201*11b9c3b1SVijay Khemka     ipmiStorageGetSELInfo()
202*11b9c3b1SVijay Khemka {
203*11b9c3b1SVijay Khemka 
204*11b9c3b1SVijay Khemka     fb_oem::ipmi::sel::GetSELInfoData info;
205*11b9c3b1SVijay Khemka 
206*11b9c3b1SVijay Khemka     selObj.getInfo(info);
207*11b9c3b1SVijay Khemka     return ipmi::responseSuccess(info.selVersion, info.entries, info.freeSpace,
208*11b9c3b1SVijay Khemka                                  info.addTimeStamp, info.eraseTimeStamp,
209*11b9c3b1SVijay Khemka                                  info.operationSupport);
210*11b9c3b1SVijay Khemka }
211*11b9c3b1SVijay Khemka 
212*11b9c3b1SVijay Khemka ipmi::RspType<uint16_t, std::vector<uint8_t>>
213*11b9c3b1SVijay Khemka     ipmiStorageGetSELEntry(std::vector<uint8_t> data)
214*11b9c3b1SVijay Khemka {
215*11b9c3b1SVijay Khemka 
216*11b9c3b1SVijay Khemka     if (data.size() != sizeof(fb_oem::ipmi::sel::GetSELEntryRequest))
217*11b9c3b1SVijay Khemka     {
218*11b9c3b1SVijay Khemka         return ipmi::responseReqDataLenInvalid();
219*11b9c3b1SVijay Khemka     }
220*11b9c3b1SVijay Khemka 
221*11b9c3b1SVijay Khemka     fb_oem::ipmi::sel::GetSELEntryRequest *reqData =
222*11b9c3b1SVijay Khemka         reinterpret_cast<fb_oem::ipmi::sel::GetSELEntryRequest *>(&data[0]);
223*11b9c3b1SVijay Khemka 
224*11b9c3b1SVijay Khemka     if (reqData->reservID != 0)
225*11b9c3b1SVijay Khemka     {
226*11b9c3b1SVijay Khemka         if (!checkSELReservation(reqData->reservID))
227*11b9c3b1SVijay Khemka         {
228*11b9c3b1SVijay Khemka             return ipmi::responseInvalidReservationId();
229*11b9c3b1SVijay Khemka         }
230*11b9c3b1SVijay Khemka     }
231*11b9c3b1SVijay Khemka 
232*11b9c3b1SVijay Khemka     uint16_t selCnt = selObj.getCount();
233*11b9c3b1SVijay Khemka     if (selCnt == 0)
234*11b9c3b1SVijay Khemka     {
235*11b9c3b1SVijay Khemka         return ipmi::responseSensorInvalid();
236*11b9c3b1SVijay Khemka     }
237*11b9c3b1SVijay Khemka 
238*11b9c3b1SVijay Khemka     /* If it is asked for first entry */
239*11b9c3b1SVijay Khemka     if (reqData->recordID == fb_oem::ipmi::sel::firstEntry)
240*11b9c3b1SVijay Khemka     {
241*11b9c3b1SVijay Khemka         /* First Entry (0x0000) as per Spec */
242*11b9c3b1SVijay Khemka         reqData->recordID = 1;
243*11b9c3b1SVijay Khemka     }
244*11b9c3b1SVijay Khemka     else if (reqData->recordID == fb_oem::ipmi::sel::lastEntry)
245*11b9c3b1SVijay Khemka     {
246*11b9c3b1SVijay Khemka         /* Last entry (0xFFFF) as per Spec */
247*11b9c3b1SVijay Khemka         reqData->recordID = selCnt;
248*11b9c3b1SVijay Khemka     }
249*11b9c3b1SVijay Khemka 
250*11b9c3b1SVijay Khemka     std::string ipmiRaw;
251*11b9c3b1SVijay Khemka 
252*11b9c3b1SVijay Khemka     if (selObj.getEntry(reqData->recordID, ipmiRaw) < 0)
253*11b9c3b1SVijay Khemka     {
254*11b9c3b1SVijay Khemka         return ipmi::responseSensorInvalid();
255*11b9c3b1SVijay Khemka     }
256*11b9c3b1SVijay Khemka 
257*11b9c3b1SVijay Khemka     std::vector<uint8_t> recDataBytes;
258*11b9c3b1SVijay Khemka     if (fromHexStr(ipmiRaw, recDataBytes) < 0)
259*11b9c3b1SVijay Khemka     {
260*11b9c3b1SVijay Khemka         return ipmi::responseUnspecifiedError();
261*11b9c3b1SVijay Khemka     }
262*11b9c3b1SVijay Khemka 
263*11b9c3b1SVijay Khemka     /* Identify the next SEL record ID. If recordID is same as
264*11b9c3b1SVijay Khemka      * total SeL count then next id should be last entry else
265*11b9c3b1SVijay Khemka      * it should be incremented by 1 to current RecordID
266*11b9c3b1SVijay Khemka      */
267*11b9c3b1SVijay Khemka     uint16_t nextRecord;
268*11b9c3b1SVijay Khemka     if (reqData->recordID == selCnt)
269*11b9c3b1SVijay Khemka     {
270*11b9c3b1SVijay Khemka         nextRecord = fb_oem::ipmi::sel::lastEntry;
271*11b9c3b1SVijay Khemka     }
272*11b9c3b1SVijay Khemka     else
273*11b9c3b1SVijay Khemka     {
274*11b9c3b1SVijay Khemka         nextRecord = reqData->recordID + 1;
275*11b9c3b1SVijay Khemka     }
276*11b9c3b1SVijay Khemka 
277*11b9c3b1SVijay Khemka     if (reqData->readLen == fb_oem::ipmi::sel::entireRecord)
278*11b9c3b1SVijay Khemka     {
279*11b9c3b1SVijay Khemka         return ipmi::responseSuccess(nextRecord, recDataBytes);
280*11b9c3b1SVijay Khemka     }
281*11b9c3b1SVijay Khemka     else
282*11b9c3b1SVijay Khemka     {
283*11b9c3b1SVijay Khemka         if (reqData->offset >= fb_oem::ipmi::sel::selRecordSize ||
284*11b9c3b1SVijay Khemka             reqData->readLen > fb_oem::ipmi::sel::selRecordSize)
285*11b9c3b1SVijay Khemka         {
286*11b9c3b1SVijay Khemka             return ipmi::responseUnspecifiedError();
287*11b9c3b1SVijay Khemka         }
288*11b9c3b1SVijay Khemka         std::vector<uint8_t> recPartData;
289*11b9c3b1SVijay Khemka 
290*11b9c3b1SVijay Khemka         auto diff = fb_oem::ipmi::sel::selRecordSize - reqData->offset;
291*11b9c3b1SVijay Khemka         auto readLength = std::min(diff, static_cast<int>(reqData->readLen));
292*11b9c3b1SVijay Khemka 
293*11b9c3b1SVijay Khemka         for (int i = 0; i < readLength; i++)
294*11b9c3b1SVijay Khemka         {
295*11b9c3b1SVijay Khemka             recPartData.push_back(recDataBytes[i + reqData->offset]);
296*11b9c3b1SVijay Khemka         }
297*11b9c3b1SVijay Khemka         return ipmi::responseSuccess(nextRecord, recPartData);
298*11b9c3b1SVijay Khemka     }
299*11b9c3b1SVijay Khemka }
300*11b9c3b1SVijay Khemka 
301*11b9c3b1SVijay Khemka ipmi::RspType<uint16_t> ipmiStorageAddSELEntry(std::vector<uint8_t> data)
302*11b9c3b1SVijay Khemka {
303*11b9c3b1SVijay Khemka     /* Per the IPMI spec, need to cancel any reservation when a
304*11b9c3b1SVijay Khemka      * SEL entry is added
305*11b9c3b1SVijay Khemka      */
306*11b9c3b1SVijay Khemka     cancelSELReservation();
307*11b9c3b1SVijay Khemka 
308*11b9c3b1SVijay Khemka     if (data.size() != fb_oem::ipmi::sel::selRecordSize)
309*11b9c3b1SVijay Khemka     {
310*11b9c3b1SVijay Khemka         return ipmi::responseReqDataLenInvalid();
311*11b9c3b1SVijay Khemka     }
312*11b9c3b1SVijay Khemka 
313*11b9c3b1SVijay Khemka     std::string ipmiRaw, logErr;
314*11b9c3b1SVijay Khemka     toHexStr(data, ipmiRaw);
315*11b9c3b1SVijay Khemka 
316*11b9c3b1SVijay Khemka     /* Log the Raw SEL message to the journal */
317*11b9c3b1SVijay Khemka     std::string journalMsg = "SEL Entry Added: " + ipmiRaw;
318*11b9c3b1SVijay Khemka     phosphor::logging::log<phosphor::logging::level::INFO>(journalMsg.c_str());
319*11b9c3b1SVijay Khemka 
320*11b9c3b1SVijay Khemka     int responseID = selObj.addEntry(ipmiRaw.c_str());
321*11b9c3b1SVijay Khemka     if (responseID < 0)
322*11b9c3b1SVijay Khemka     {
323*11b9c3b1SVijay Khemka         return ipmi::responseUnspecifiedError();
324*11b9c3b1SVijay Khemka     }
325*11b9c3b1SVijay Khemka     return ipmi::responseSuccess((uint16_t)responseID);
326*11b9c3b1SVijay Khemka }
327*11b9c3b1SVijay Khemka 
328*11b9c3b1SVijay Khemka void registerSELFunctions()
329*11b9c3b1SVijay Khemka {
330*11b9c3b1SVijay Khemka     // <Get SEL Info>
331*11b9c3b1SVijay Khemka     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
332*11b9c3b1SVijay Khemka                           ipmi::storage::cmdGetSelInfo, ipmi::Privilege::User,
333*11b9c3b1SVijay Khemka                           ipmiStorageGetSELInfo);
334*11b9c3b1SVijay Khemka 
335*11b9c3b1SVijay Khemka     // <Get SEL Entry>
336*11b9c3b1SVijay Khemka     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
337*11b9c3b1SVijay Khemka                           ipmi::storage::cmdGetSelEntry, ipmi::Privilege::User,
338*11b9c3b1SVijay Khemka                           ipmiStorageGetSELEntry);
339*11b9c3b1SVijay Khemka 
340*11b9c3b1SVijay Khemka     // <Add SEL Entry>
341*11b9c3b1SVijay Khemka     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
342*11b9c3b1SVijay Khemka                           ipmi::storage::cmdAddSelEntry,
343*11b9c3b1SVijay Khemka                           ipmi::Privilege::Operator, ipmiStorageAddSELEntry);
344*11b9c3b1SVijay Khemka 
345*11b9c3b1SVijay Khemka     return;
346*11b9c3b1SVijay Khemka }
347*11b9c3b1SVijay Khemka 
348*11b9c3b1SVijay Khemka } // namespace storage
349*11b9c3b1SVijay Khemka } // namespace ipmi
350