blob: ced34eb0459c02ac27cd11059e9fab82c93d856f [file] [log] [blame]
Patrick Venture3a5071a2018-09-12 13:27:42 -07001#include "storagehandler.hpp"
2
3#include "fruread.hpp"
4#include "read_fru_data.hpp"
5#include "selutility.hpp"
6#include "sensorhandler.hpp"
7#include "storageaddsel.hpp"
Patrick Venture3a5071a2018-09-12 13:27:42 -07008
Lei YU52d91242017-10-17 22:52:28 +08009#include <arpa/inet.h>
Patrick Venture3a5071a2018-09-12 13:27:42 -070010#include <mapper.h>
11#include <systemd/sd-bus.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070012
13#include <algorithm>
Lei YU52d91242017-10-17 22:52:28 +080014#include <chrono>
15#include <cstdio>
Patrick Ventureb51bf9c2018-09-10 15:53:14 -070016#include <cstring>
Vernon Mauerybdda8002019-02-26 10:18:51 -080017#include <filesystem>
Vernon Mauerye08fbff2019-04-03 09:19:34 -070018#include <ipmid/api.hpp>
Vernon Mauery6a98fe72019-03-11 15:57:48 -070019#include <ipmid/utils.hpp>
Patrick Venture3a5071a2018-09-12 13:27:42 -070020#include <phosphor-logging/elog-errors.hpp>
21#include <phosphor-logging/log.hpp>
22#include <sdbusplus/server.hpp>
23#include <string>
Vernon Mauery16b86932019-05-01 08:36:11 -070024#include <variant>
Patrick Venture3a5071a2018-09-12 13:27:42 -070025#include <xyz/openbmc_project/Common/error.hpp>
26
Chris Austenb4f5b922015-10-13 12:44:43 -050027void register_netfn_storage_functions() __attribute__((constructor));
28
Patrick Venture0b02be92018-08-31 11:55:55 -070029unsigned int g_sel_time = 0xFFFFFFFF;
Patrick Venturedb0cbe62019-09-09 14:47:22 -070030namespace ipmi
31{
32namespace sensor
33{
34extern const IdInfoMap sensors;
35} // namespace sensor
36} // namespace ipmi
37
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -060038extern const FruMap frus;
anil kumar appana2c7db1d2019-05-28 11:20:19 +000039constexpr uint8_t eventDataSize = 3;
Patrick Venture0b02be92018-08-31 11:55:55 -070040namespace
41{
Lei YUe8939392017-06-15 10:45:05 +080042constexpr auto TIME_INTERFACE = "xyz.openbmc_project.Time.EpochTime";
George Liu4d623e92020-05-25 16:51:57 +080043constexpr auto BMC_TIME_PATH = "/xyz/openbmc_project/time/bmc";
Lei YUe8939392017-06-15 10:45:05 +080044constexpr auto DBUS_PROPERTIES = "org.freedesktop.DBus.Properties";
Patrick Venture0b02be92018-08-31 11:55:55 -070045constexpr auto PROPERTY_ELAPSED = "Elapsed";
Lei YUe8939392017-06-15 10:45:05 +080046
Lei YUd9555252021-09-14 20:30:41 +080047constexpr auto logWatchPath = "/xyz/openbmc_project/logging";
Lei YUd9e57662021-09-14 18:06:28 +080048constexpr auto logBasePath = "/xyz/openbmc_project/logging/entry";
49constexpr auto logEntryIntf = "xyz.openbmc_project.Logging.Entry";
50constexpr auto logDeleteIntf = "xyz.openbmc_project.Object.Delete";
Patrick Venture0b02be92018-08-31 11:55:55 -070051} // namespace
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +053052
Tom Joseph6f7deaa2017-06-30 19:03:54 +053053namespace cache
54{
Patrick Venture0b02be92018-08-31 11:55:55 -070055/*
56 * This cache contains the object paths of the logging entries sorted in the
57 * order of the filename(numeric order). The cache is initialized by
58 * invoking readLoggingObjectPaths with the cache as the parameter. The
59 * cache is invoked in the execution of the Get SEL info and Delete SEL
60 * entry command. The Get SEL Info command is typically invoked before the
61 * Get SEL entry command, so the cache is utilized for responding to Get SEL
62 * entry command. The cache is invalidated by clearing after Delete SEL
63 * entry and Clear SEL command.
64 */
65ipmi::sel::ObjectPaths paths;
Tom Joseph6f7deaa2017-06-30 19:03:54 +053066
Patrick Venture0b02be92018-08-31 11:55:55 -070067} // namespace cache
Tom Joseph6f7deaa2017-06-30 19:03:54 +053068
69using InternalFailure =
Patrick Venture0b02be92018-08-31 11:55:55 -070070 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Tom Joseph6f7deaa2017-06-30 19:03:54 +053071using namespace phosphor::logging;
Marri Devender Raocac383b2017-07-03 13:24:27 -050072using namespace ipmi::fru;
73
Lei YUd9e57662021-09-14 18:06:28 +080074using SELRecordID = uint16_t;
75using SELEntry = ipmi::sel::SELEventRecordFormat;
76using SELCacheMap = std::map<SELRecordID, SELEntry>;
77
78SELCacheMap selCacheMap __attribute__((init_priority(101)));
Lei YUd9555252021-09-14 20:30:41 +080079std::unique_ptr<sdbusplus::bus::match::match> selAddedMatch
80 __attribute__((init_priority(101)));
Lei YUb6b72b02021-09-14 21:06:05 +080081std::unique_ptr<sdbusplus::bus::match::match> selRemovedMatch
82 __attribute__((init_priority(101)));
Lei YUd9e57662021-09-14 18:06:28 +080083
Lei YUb6b72b02021-09-14 21:06:05 +080084static inline uint16_t getLoggingId(const std::string& p)
Lei YUd9e57662021-09-14 18:06:28 +080085{
86 namespace fs = std::filesystem;
87 fs::path entryPath(p);
Lei YUb6b72b02021-09-14 21:06:05 +080088 return std::stoul(entryPath.filename().string());
89}
90
91std::pair<uint16_t, SELEntry> parseLoggingEntry(const std::string& p)
92{
93 auto id = getLoggingId(p);
Lei YUd9e57662021-09-14 18:06:28 +080094 // TODO: parse the sel data
95 return {id, {}};
96}
97
Lei YUd9555252021-09-14 20:30:41 +080098static void selAddedCallback(sdbusplus::message::message& m)
99{
100 sdbusplus::message::object_path objPath;
101 try
102 {
103 m.read(objPath);
104 }
105 catch (const sdbusplus::exception::exception& e)
106 {
107 log<level::ERR>("Failed to read object path");
108 return;
109 }
110 std::string p = objPath;
111 selCacheMap.insert(parseLoggingEntry(p));
112}
113
Lei YUb6b72b02021-09-14 21:06:05 +0800114static void selRemovedCallback(sdbusplus::message::message& m)
115{
116 sdbusplus::message::object_path objPath;
117 try
118 {
119 m.read(objPath);
120 }
121 catch (const sdbusplus::exception::exception& e)
122 {
123 log<level::ERR>("Failed to read object path");
124 return;
125 }
126 std::string p = objPath;
127 selCacheMap.erase(getLoggingId(p));
128}
129
Lei YUd9555252021-09-14 20:30:41 +0800130void registerSelCallbackHandler()
131{
132 using namespace sdbusplus::bus::match::rules;
133 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
134 if (!selAddedMatch)
135 {
136 selAddedMatch = std::make_unique<sdbusplus::bus::match::match>(
137 bus, interfacesAdded(logWatchPath),
138 std::bind(selAddedCallback, std::placeholders::_1));
139 }
Lei YUb6b72b02021-09-14 21:06:05 +0800140 if (!selRemovedMatch)
141 {
142 selRemovedMatch = std::make_unique<sdbusplus::bus::match::match>(
143 bus, interfacesRemoved(logWatchPath),
144 std::bind(selRemovedCallback, std::placeholders::_1));
145 }
Lei YUd9555252021-09-14 20:30:41 +0800146}
147
Lei YUd9e57662021-09-14 18:06:28 +0800148void initSELCache()
149{
150 try
151 {
152 ipmi::sel::readLoggingObjectPaths(cache::paths);
153 }
154 catch (const sdbusplus::exception::exception& e)
155 {
156 log<level::ERR>("Failed to get logging object paths");
157 return;
158 }
159 for (const auto& p : cache::paths)
160 {
161 selCacheMap.insert(parseLoggingEntry(p));
162 }
Lei YUd9555252021-09-14 20:30:41 +0800163 registerSelCallbackHandler();
Lei YUd9e57662021-09-14 18:06:28 +0800164}
165
Marri Devender Raocac383b2017-07-03 13:24:27 -0500166/**
167 * @enum Device access mode
168 */
169enum class AccessMode
170{
171 bytes, ///< Device is accessed by bytes
172 words ///< Device is accessed by words
173};
174
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000175/** @brief implements the get SEL Info command
176 * @returns IPMI completion code plus response data
177 * - selVersion - SEL revision
178 * - entries - Number of log entries in SEL.
179 * - freeSpace - Free Space in bytes.
180 * - addTimeStamp - Most recent addition timestamp
181 * - eraseTimeStamp - Most recent erase timestamp
182 * - operationSupport - Reserve & Delete SEL operations supported
183 */
184
185ipmi::RspType<uint8_t, // SEL revision.
186 uint16_t, // number of log entries in SEL.
187 uint16_t, // free Space in bytes.
188 uint32_t, // most recent addition timestamp
189 uint32_t, // most recent erase timestamp.
190
191 bool, // SEL allocation info supported
192 bool, // reserve SEL supported
193 bool, // partial Add SEL Entry supported
194 bool, // delete SEL supported
195 uint3_t, // reserved
196 bool // overflow flag
197 >
198 ipmiStorageGetSelInfo()
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530199{
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000200 uint16_t entries = 0;
201 // Most recent addition timestamp.
202 uint32_t addTimeStamp = ipmi::sel::invalidTimeStamp;
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530203
Tom Josephe59abfb2018-08-06 18:46:27 +0530204 try
205 {
206 ipmi::sel::readLoggingObjectPaths(cache::paths);
207 }
Patrick Williamsef1259b2021-09-02 09:12:33 -0500208 catch (const sdbusplus::exception::exception& e)
Tom Josephe59abfb2018-08-06 18:46:27 +0530209 {
210 // No action if reading log objects have failed for this command.
211 // readLoggingObjectPaths will throw exception if there are no log
212 // entries. The command will be responded with number of SEL entries
213 // as 0.
214 }
215
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530216 if (!cache::paths.empty())
217 {
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000218 entries = static_cast<uint16_t>(cache::paths.size());
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530219
220 try
221 {
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000222 addTimeStamp = static_cast<uint32_t>(
Patrick Venture0b02be92018-08-31 11:55:55 -0700223 (ipmi::sel::getEntryTimeStamp(cache::paths.back()).count()));
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530224 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500225 catch (const InternalFailure& e)
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530226 {
227 }
228 catch (const std::runtime_error& e)
229 {
230 log<level::ERR>(e.what());
231 }
232 }
233
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000234 constexpr uint8_t selVersion = ipmi::sel::selVersion;
235 constexpr uint16_t freeSpace = 0xFFFF;
236 constexpr uint32_t eraseTimeStamp = ipmi::sel::invalidTimeStamp;
237 constexpr uint3_t reserved{0};
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530238
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000239 return ipmi::responseSuccess(
240 selVersion, entries, freeSpace, addTimeStamp, eraseTimeStamp,
241 ipmi::sel::operationSupport::getSelAllocationInfo,
242 ipmi::sel::operationSupport::reserveSel,
243 ipmi::sel::operationSupport::partialAddSelEntry,
244 ipmi::sel::operationSupport::deleteSel, reserved,
245 ipmi::sel::operationSupport::overflow);
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530246}
247
Tom Josepha4953392017-06-30 19:09:47 +0530248ipmi_ret_t getSELEntry(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
249 ipmi_request_t request, ipmi_response_t response,
250 ipmi_data_len_t data_len, ipmi_context_t context)
251{
Jason M. Bills851acb12019-02-04 14:06:57 -0800252 if (*data_len != sizeof(ipmi::sel::GetSELEntryRequest))
253 {
254 *data_len = 0;
255 return IPMI_CC_REQ_DATA_LEN_INVALID;
256 }
257
Patrick Venture0b02be92018-08-31 11:55:55 -0700258 auto requestData =
259 reinterpret_cast<const ipmi::sel::GetSELEntryRequest*>(request);
Tom Josepha4953392017-06-30 19:09:47 +0530260
261 if (requestData->reservationID != 0)
262 {
Jason M. Bills13e67c82018-09-10 14:12:16 -0700263 if (!checkSELReservation(requestData->reservationID))
Tom Josepha4953392017-06-30 19:09:47 +0530264 {
265 *data_len = 0;
266 return IPMI_CC_INVALID_RESERVATION_ID;
267 }
268 }
269
270 if (cache::paths.empty())
271 {
272 *data_len = 0;
273 return IPMI_CC_SENSOR_INVALID;
274 }
275
276 ipmi::sel::ObjectPaths::const_iterator iter;
277
278 // Check for the requested SEL Entry.
279 if (requestData->selRecordID == ipmi::sel::firstEntry)
280 {
281 iter = cache::paths.begin();
282 }
283 else if (requestData->selRecordID == ipmi::sel::lastEntry)
284 {
285 iter = cache::paths.end();
286 }
287 else
288 {
289 std::string objPath = std::string(ipmi::sel::logBasePath) + "/" +
290 std::to_string(requestData->selRecordID);
291
292 iter = std::find(cache::paths.begin(), cache::paths.end(), objPath);
293 if (iter == cache::paths.end())
294 {
295 *data_len = 0;
296 return IPMI_CC_SENSOR_INVALID;
297 }
298 }
299
Patrick Venture0b02be92018-08-31 11:55:55 -0700300 ipmi::sel::GetSELEntryResponse record{};
Tom Josepha4953392017-06-30 19:09:47 +0530301
302 // Convert the log entry into SEL record.
303 try
304 {
305 record = ipmi::sel::convertLogEntrytoSEL(*iter);
306 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500307 catch (const InternalFailure& e)
Tom Josepha4953392017-06-30 19:09:47 +0530308 {
309 *data_len = 0;
310 return IPMI_CC_UNSPECIFIED_ERROR;
311 }
312 catch (const std::runtime_error& e)
313 {
314 log<level::ERR>(e.what());
315 *data_len = 0;
316 return IPMI_CC_UNSPECIFIED_ERROR;
317 }
318
Tom Josepha4953392017-06-30 19:09:47 +0530319 // Identify the next SEL record ID
Patrick Venture0b02be92018-08-31 11:55:55 -0700320 if (iter != cache::paths.end())
Tom Josepha4953392017-06-30 19:09:47 +0530321 {
322 ++iter;
323 if (iter == cache::paths.end())
324 {
325 record.nextRecordID = ipmi::sel::lastEntry;
326 }
327 else
328 {
Vernon Mauery185b9f82018-07-20 10:52:36 -0700329 namespace fs = std::filesystem;
Tom Josepha4953392017-06-30 19:09:47 +0530330 fs::path path(*iter);
Patrick Venture0b02be92018-08-31 11:55:55 -0700331 record.nextRecordID = static_cast<uint16_t>(
332 std::stoul(std::string(path.filename().c_str())));
Tom Josepha4953392017-06-30 19:09:47 +0530333 }
334 }
335 else
336 {
337 record.nextRecordID = ipmi::sel::lastEntry;
338 }
339
340 if (requestData->readLength == ipmi::sel::entireRecord)
341 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700342 std::memcpy(response, &record, sizeof(record));
Tom Josepha4953392017-06-30 19:09:47 +0530343 *data_len = sizeof(record);
344 }
345 else
346 {
347 if (requestData->offset >= ipmi::sel::selRecordSize ||
348 requestData->readLength > ipmi::sel::selRecordSize)
349 {
350 *data_len = 0;
351 return IPMI_CC_INVALID_FIELD_REQUEST;
352 }
353
354 auto diff = ipmi::sel::selRecordSize - requestData->offset;
Patrick Venture0b02be92018-08-31 11:55:55 -0700355 auto readLength =
356 std::min(diff, static_cast<int>(requestData->readLength));
Tom Josepha4953392017-06-30 19:09:47 +0530357
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700358 std::memcpy(response, &record.nextRecordID,
359 sizeof(record.nextRecordID));
360 std::memcpy(static_cast<uint8_t*>(response) +
361 sizeof(record.nextRecordID),
Lei YUaf378fa2020-12-02 16:28:57 +0800362 &record.event.eventRecord.recordID + requestData->offset,
363 readLength);
Tom Josepha4953392017-06-30 19:09:47 +0530364 *data_len = sizeof(record.nextRecordID) + readLength;
365 }
366
367 return IPMI_CC_OK;
368}
369
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000370/** @brief implements the delete SEL entry command
371 * @request
372 * - reservationID; // reservation ID.
373 * - selRecordID; // SEL record ID.
374 *
375 * @returns ipmi completion code plus response data
376 * - Record ID of the deleted record
377 */
378ipmi::RspType<uint16_t // deleted record ID
379 >
380 deleteSELEntry(uint16_t reservationID, uint16_t selRecordID)
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530381{
Jason M. Bills851acb12019-02-04 14:06:57 -0800382
Brad Bishop1a4117b2018-11-21 15:48:18 -0500383 namespace fs = std::filesystem;
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530384
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000385 if (!checkSELReservation(reservationID))
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530386 {
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000387 return ipmi::responseInvalidReservationId();
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530388 }
389
Jason M. Bills13e67c82018-09-10 14:12:16 -0700390 // Per the IPMI spec, need to cancel the reservation when a SEL entry is
391 // deleted
392 cancelSELReservation();
393
Tom Josephe59abfb2018-08-06 18:46:27 +0530394 try
395 {
396 ipmi::sel::readLoggingObjectPaths(cache::paths);
397 }
Patrick Williamsef1259b2021-09-02 09:12:33 -0500398 catch (const sdbusplus::exception::exception& e)
Tom Josephe59abfb2018-08-06 18:46:27 +0530399 {
400 // readLoggingObjectPaths will throw exception if there are no error
401 // log entries.
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000402 return ipmi::responseSensorInvalid();
Tom Josephe59abfb2018-08-06 18:46:27 +0530403 }
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530404
405 if (cache::paths.empty())
406 {
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000407 return ipmi::responseSensorInvalid();
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530408 }
409
410 ipmi::sel::ObjectPaths::const_iterator iter;
411 uint16_t delRecordID = 0;
412
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000413 if (selRecordID == ipmi::sel::firstEntry)
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530414 {
415 iter = cache::paths.begin();
416 fs::path path(*iter);
Patrick Venture0b02be92018-08-31 11:55:55 -0700417 delRecordID = static_cast<uint16_t>(
418 std::stoul(std::string(path.filename().c_str())));
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530419 }
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000420 else if (selRecordID == ipmi::sel::lastEntry)
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530421 {
422 iter = cache::paths.end();
423 fs::path path(*iter);
Patrick Venture0b02be92018-08-31 11:55:55 -0700424 delRecordID = static_cast<uint16_t>(
425 std::stoul(std::string(path.filename().c_str())));
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530426 }
427 else
428 {
429 std::string objPath = std::string(ipmi::sel::logBasePath) + "/" +
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000430 std::to_string(selRecordID);
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530431
432 iter = std::find(cache::paths.begin(), cache::paths.end(), objPath);
433 if (iter == cache::paths.end())
434 {
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000435 return ipmi::responseSensorInvalid();
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530436 }
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000437 delRecordID = selRecordID;
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530438 }
439
440 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
441 std::string service;
442
443 try
444 {
445 service = ipmi::getService(bus, ipmi::sel::logDeleteIntf, *iter);
446 }
447 catch (const std::runtime_error& e)
448 {
449 log<level::ERR>(e.what());
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000450 return ipmi::responseUnspecifiedError();
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530451 }
452
Patrick Venture0b02be92018-08-31 11:55:55 -0700453 auto methodCall = bus.new_method_call(service.c_str(), (*iter).c_str(),
454 ipmi::sel::logDeleteIntf, "Delete");
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530455 auto reply = bus.call(methodCall);
456 if (reply.is_method_error())
457 {
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000458 return ipmi::responseUnspecifiedError();
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530459 }
460
461 // Invalidate the cache of dbus entry objects.
462 cache::paths.clear();
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530463
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000464 return ipmi::responseSuccess(delRecordID);
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530465}
466
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000467/** @brief implements the Clear SEL command
468 * @request
469 * - reservationID // Reservation ID.
470 * - clr // char array { 'C'(0x43h), 'L'(0x4Ch), 'R'(0x52h) }
471 * - eraseOperation; // requested operation.
472 *
473 * @returns ipmi completion code plus response data
474 * - erase status
475 */
476
477ipmi::RspType<uint8_t // erase status
478 >
479 clearSEL(uint16_t reservationID, const std::array<char, 3>& clr,
480 uint8_t eraseOperation)
Tom Joseph2f05bb52017-06-30 19:14:49 +0530481{
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000482 static constexpr std::array<char, 3> clrOk = {'C', 'L', 'R'};
483 if (clr != clrOk)
Jason M. Bills851acb12019-02-04 14:06:57 -0800484 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000485 return ipmi::responseInvalidFieldRequest();
Jason M. Bills851acb12019-02-04 14:06:57 -0800486 }
487
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000488 if (!checkSELReservation(reservationID))
Tom Joseph2f05bb52017-06-30 19:14:49 +0530489 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000490 return ipmi::responseInvalidReservationId();
Tom Joseph2f05bb52017-06-30 19:14:49 +0530491 }
492
Tom Joseph2f05bb52017-06-30 19:14:49 +0530493 /*
494 * Erasure status cannot be fetched from DBUS, so always return erasure
495 * status as `erase completed`.
496 */
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000497 if (eraseOperation == ipmi::sel::getEraseStatus)
Tom Joseph2f05bb52017-06-30 19:14:49 +0530498 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000499 return ipmi::responseSuccess(
500 static_cast<uint8_t>(ipmi::sel::eraseComplete));
Tom Joseph2f05bb52017-06-30 19:14:49 +0530501 }
502
Jason M. Bills13e67c82018-09-10 14:12:16 -0700503 // Per the IPMI spec, need to cancel any reservation when the SEL is cleared
504 cancelSELReservation();
505
Tom Joseph2f05bb52017-06-30 19:14:49 +0530506 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Tom Josephe59abfb2018-08-06 18:46:27 +0530507 ipmi::sel::ObjectPaths objectPaths;
Tom Joseph2f05bb52017-06-30 19:14:49 +0530508 auto depth = 0;
509
Patrick Venture0b02be92018-08-31 11:55:55 -0700510 auto mapperCall =
511 bus.new_method_call(ipmi::sel::mapperBusName, ipmi::sel::mapperObjPath,
512 ipmi::sel::mapperIntf, "GetSubTreePaths");
Tom Joseph2f05bb52017-06-30 19:14:49 +0530513 mapperCall.append(ipmi::sel::logBasePath);
514 mapperCall.append(depth);
515 mapperCall.append(ipmi::sel::ObjectPaths({ipmi::sel::logEntryIntf}));
516
Tom Josephe59abfb2018-08-06 18:46:27 +0530517 try
Tom Joseph2f05bb52017-06-30 19:14:49 +0530518 {
Tom Josephe59abfb2018-08-06 18:46:27 +0530519 auto reply = bus.call(mapperCall);
520 if (reply.is_method_error())
521 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000522 return ipmi::responseSuccess(
523 static_cast<uint8_t>(ipmi::sel::eraseComplete));
Tom Josephe59abfb2018-08-06 18:46:27 +0530524 }
Tom Joseph2f05bb52017-06-30 19:14:49 +0530525
Tom Josephe59abfb2018-08-06 18:46:27 +0530526 reply.read(objectPaths);
527 if (objectPaths.empty())
528 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000529 return ipmi::responseSuccess(
530 static_cast<uint8_t>(ipmi::sel::eraseComplete));
Tom Josephe59abfb2018-08-06 18:46:27 +0530531 }
532 }
Patrick Williamsef1259b2021-09-02 09:12:33 -0500533 catch (const sdbusplus::exception::exception& e)
Tom Joseph2f05bb52017-06-30 19:14:49 +0530534 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000535 return ipmi::responseSuccess(
536 static_cast<uint8_t>(ipmi::sel::eraseComplete));
Tom Joseph2f05bb52017-06-30 19:14:49 +0530537 }
538
539 std::string service;
540
541 try
542 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700543 service = ipmi::getService(bus, ipmi::sel::logDeleteIntf,
Tom Joseph2f05bb52017-06-30 19:14:49 +0530544 objectPaths.front());
545 }
546 catch (const std::runtime_error& e)
547 {
548 log<level::ERR>(e.what());
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000549 return ipmi::responseUnspecifiedError();
Tom Joseph2f05bb52017-06-30 19:14:49 +0530550 }
551
552 for (const auto& iter : objectPaths)
553 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700554 auto methodCall = bus.new_method_call(
555 service.c_str(), iter.c_str(), ipmi::sel::logDeleteIntf, "Delete");
Tom Joseph2f05bb52017-06-30 19:14:49 +0530556
557 auto reply = bus.call(methodCall);
558 if (reply.is_method_error())
559 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000560 return ipmi::responseUnspecifiedError();
Tom Joseph2f05bb52017-06-30 19:14:49 +0530561 }
562 }
563
564 // Invalidate the cache of dbus entry objects.
565 cache::paths.clear();
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000566 return ipmi::responseSuccess(
567 static_cast<uint8_t>(ipmi::sel::eraseComplete));
Tom Joseph2f05bb52017-06-30 19:14:49 +0530568}
569
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000570/** @brief implements the get SEL time command
571 * @returns IPMI completion code plus response data
572 * -current time
573 */
574ipmi::RspType<uint32_t> // current time
575 ipmiStorageGetSelTime()
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500576{
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530577 using namespace std::chrono;
George Liu4d623e92020-05-25 16:51:57 +0800578 uint64_t bmc_time_usec = 0;
579 std::stringstream bmcTime;
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500580
Lei YUe8939392017-06-15 10:45:05 +0800581 try
582 {
583 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
George Liu4d623e92020-05-25 16:51:57 +0800584 auto service = ipmi::getService(bus, TIME_INTERFACE, BMC_TIME_PATH);
Vernon Mauery16b86932019-05-01 08:36:11 -0700585 std::variant<uint64_t> value;
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530586
George Liu4d623e92020-05-25 16:51:57 +0800587 // Get bmc time
588 auto method = bus.new_method_call(service.c_str(), BMC_TIME_PATH,
Patrick Venture0b02be92018-08-31 11:55:55 -0700589 DBUS_PROPERTIES, "Get");
Lei YUe8939392017-06-15 10:45:05 +0800590
591 method.append(TIME_INTERFACE, PROPERTY_ELAPSED);
592 auto reply = bus.call(method);
593 if (reply.is_method_error())
594 {
595 log<level::ERR>("Error getting time",
596 entry("SERVICE=%s", service.c_str()),
George Liu4d623e92020-05-25 16:51:57 +0800597 entry("PATH=%s", BMC_TIME_PATH));
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000598 return ipmi::responseUnspecifiedError();
Lei YUe8939392017-06-15 10:45:05 +0800599 }
600 reply.read(value);
George Liu4d623e92020-05-25 16:51:57 +0800601 bmc_time_usec = std::get<uint64_t>(value);
Lei YUe8939392017-06-15 10:45:05 +0800602 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500603 catch (const InternalFailure& e)
Lei YUe8939392017-06-15 10:45:05 +0800604 {
605 log<level::ERR>(e.what());
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000606 return ipmi::responseUnspecifiedError();
Lei YUe8939392017-06-15 10:45:05 +0800607 }
Tom Joseph30fd0a12019-09-24 06:53:22 +0530608 catch (const std::exception& e)
Lei YUe8939392017-06-15 10:45:05 +0800609 {
610 log<level::ERR>(e.what());
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000611 return ipmi::responseUnspecifiedError();
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530612 }
613
George Liu4d623e92020-05-25 16:51:57 +0800614 bmcTime << "BMC time:"
615 << duration_cast<seconds>(microseconds(bmc_time_usec)).count();
616 log<level::DEBUG>(bmcTime.str().c_str());
Nagaraju Goruganti8960b7c2018-04-29 22:38:40 -0500617
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530618 // Time is really long int but IPMI wants just uint32. This works okay until
619 // the number of seconds since 1970 overflows uint32 size.. Still a whole
620 // lot of time here to even think about that.
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000621 return ipmi::responseSuccess(
George Liu4d623e92020-05-25 16:51:57 +0800622 duration_cast<seconds>(microseconds(bmc_time_usec)).count());
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500623}
624
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000625/** @brief implements the set SEL time command
626 * @param selDeviceTime - epoch time
627 * -local time as the number of seconds from 00:00:00, January 1, 1970
628 * @returns IPMI completion code
629 */
630ipmi::RspType<> ipmiStorageSetSelTime(uint32_t selDeviceTime)
Chris Austenb4f5b922015-10-13 12:44:43 -0500631{
Lei YUe8939392017-06-15 10:45:05 +0800632 using namespace std::chrono;
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000633 microseconds usec{seconds(selDeviceTime)};
Norman James82330442015-11-19 16:53:26 -0600634
Lei YUe8939392017-06-15 10:45:05 +0800635 try
636 {
637 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
George Liu4d623e92020-05-25 16:51:57 +0800638 auto service = ipmi::getService(bus, TIME_INTERFACE, BMC_TIME_PATH);
Andrew Geissler6467ed22020-05-16 16:03:53 -0500639 std::variant<uint64_t> value{(uint64_t)usec.count()};
Lei YUe8939392017-06-15 10:45:05 +0800640
George Liu4d623e92020-05-25 16:51:57 +0800641 // Set bmc time
642 auto method = bus.new_method_call(service.c_str(), BMC_TIME_PATH,
Patrick Venture0b02be92018-08-31 11:55:55 -0700643 DBUS_PROPERTIES, "Set");
Lei YUe8939392017-06-15 10:45:05 +0800644
645 method.append(TIME_INTERFACE, PROPERTY_ELAPSED, value);
646 auto reply = bus.call(method);
647 if (reply.is_method_error())
648 {
649 log<level::ERR>("Error setting time",
650 entry("SERVICE=%s", service.c_str()),
George Liu4d623e92020-05-25 16:51:57 +0800651 entry("PATH=%s", BMC_TIME_PATH));
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000652 return ipmi::responseUnspecifiedError();
Lei YUe8939392017-06-15 10:45:05 +0800653 }
Norman James82330442015-11-19 16:53:26 -0600654 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500655 catch (const InternalFailure& e)
Lei YUe8939392017-06-15 10:45:05 +0800656 {
657 log<level::ERR>(e.what());
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000658 return ipmi::responseUnspecifiedError();
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530659 }
Tom Joseph30fd0a12019-09-24 06:53:22 +0530660 catch (const std::exception& e)
Lei YUe8939392017-06-15 10:45:05 +0800661 {
662 log<level::ERR>(e.what());
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000663 return ipmi::responseUnspecifiedError();
Norman James82330442015-11-19 16:53:26 -0600664 }
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530665
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000666 return ipmi::responseSuccess();
Chris Austenb4f5b922015-10-13 12:44:43 -0500667}
668
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000669/** @brief implements the reserve SEL command
670 * @returns IPMI completion code plus response data
671 * - SEL reservation ID.
672 */
673ipmi::RspType<uint16_t> ipmiStorageReserveSel()
Chris Austenb4f5b922015-10-13 12:44:43 -0500674{
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000675 return ipmi::responseSuccess(reserveSel());
Chris Austenb4f5b922015-10-13 12:44:43 -0500676}
677
anil kumar appana2c7db1d2019-05-28 11:20:19 +0000678/** @brief implements the Add SEL entry command
679 * @request
680 *
681 * - recordID ID used for SEL Record access
682 * - recordType Record Type
683 * - timeStamp Time when event was logged. LS byte first
684 * - generatorID software ID if event was generated from
685 * system software
686 * - evmRev event message format version
687 * - sensorType sensor type code for service that generated
688 * the event
689 * - sensorNumber number of sensors that generated the event
690 * - eventDir event dir
691 * - eventData event data field contents
692 *
693 * @returns ipmi completion code plus response data
694 * - RecordID of the Added SEL entry
695 */
696ipmi::RspType<uint16_t // recordID of the Added SEL entry
697 >
698 ipmiStorageAddSEL(uint16_t recordID, uint8_t recordType, uint32_t timeStamp,
699 uint16_t generatorID, uint8_t evmRev, uint8_t sensorType,
700 uint8_t sensorNumber, uint8_t eventDir,
701 std::array<uint8_t, eventDataSize> eventData)
Chris Austenb4f5b922015-10-13 12:44:43 -0500702{
Jason M. Bills13e67c82018-09-10 14:12:16 -0700703 // Per the IPMI spec, need to cancel the reservation when a SEL entry is
704 // added
705 cancelSELReservation();
Tom Josephb647d5b2017-10-31 17:25:33 +0530706 // Hostboot sends SEL with OEM record type 0xDE to indicate that there is
707 // a maintenance procedure associated with eSEL record.
708 static constexpr auto procedureType = 0xDE;
anil kumar appana2c7db1d2019-05-28 11:20:19 +0000709 if (recordType == procedureType)
Tom Josephb647d5b2017-10-31 17:25:33 +0530710 {
711 // In the OEM record type 0xDE, byte 11 in the SEL record indicate the
712 // procedure number.
anil kumar appana2c7db1d2019-05-28 11:20:19 +0000713 createProcedureLogEntry(sensorType);
Tom Josephb647d5b2017-10-31 17:25:33 +0530714 }
Chris Austenb4f5b922015-10-13 12:44:43 -0500715
anil kumar appana2c7db1d2019-05-28 11:20:19 +0000716 return ipmi::responseSuccess(recordID);
Chris Austenb4f5b922015-10-13 12:44:43 -0500717}
718
Kirill Pakhomovfa6e2092020-04-24 18:57:15 +0300719bool isFruPresent(const std::string& fruPath)
720{
721 using namespace ipmi::fru;
722
723 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
724
725 auto propValue =
726 ipmi::getDbusProperty(bus, invMgrInterface, invObjPath + fruPath,
727 invItemInterface, itemPresentProp);
728
729 return std::get<bool>(propValue);
730}
731
Pradeep Kumarb0c794d2019-05-02 13:09:14 +0000732/** @brief implements the get FRU Inventory Area Info command
733 *
734 * @returns IPMI completion code plus response data
735 * - FRU Inventory area size in bytes,
736 * - access bit
737 **/
738ipmi::RspType<uint16_t, // FRU Inventory area size in bytes,
739 uint8_t // access size (bytes / words)
740 >
741 ipmiStorageGetFruInvAreaInfo(uint8_t fruID)
Marri Devender Raofa7b4e22017-07-03 00:52:20 -0500742{
Tom Joseph187f5642018-03-29 13:49:06 +0530743
Pradeep Kumarb0c794d2019-05-02 13:09:14 +0000744 auto iter = frus.find(fruID);
Tom Joseph187f5642018-03-29 13:49:06 +0530745 if (iter == frus.end())
746 {
Pradeep Kumarb0c794d2019-05-02 13:09:14 +0000747 return ipmi::responseSensorInvalid();
Tom Joseph187f5642018-03-29 13:49:06 +0530748 }
749
Kirill Pakhomovfa6e2092020-04-24 18:57:15 +0300750 auto path = iter->second[0].path;
751 if (!isFruPresent(path))
752 {
753 return ipmi::responseSensorInvalid();
754 }
755
Marri Devender Raocac383b2017-07-03 13:24:27 -0500756 try
757 {
Pradeep Kumarb0c794d2019-05-02 13:09:14 +0000758 return ipmi::responseSuccess(
759 static_cast<uint16_t>(getFruAreaData(fruID).size()),
760 static_cast<uint8_t>(AccessMode::bytes));
Marri Devender Raocac383b2017-07-03 13:24:27 -0500761 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700762 catch (const InternalFailure& e)
Marri Devender Raocac383b2017-07-03 13:24:27 -0500763 {
Marri Devender Raocac383b2017-07-03 13:24:27 -0500764 log<level::ERR>(e.what());
Pradeep Kumarb0c794d2019-05-02 13:09:14 +0000765 return ipmi::responseUnspecifiedError();
Marri Devender Raocac383b2017-07-03 13:24:27 -0500766 }
Marri Devender Raofa7b4e22017-07-03 00:52:20 -0500767}
768
anil kumar appana5b7c3262019-05-27 18:10:23 +0000769/**@brief implements the Read FRU Data command
770 * @param fruDeviceId - FRU device ID. FFh = reserved
771 * @param offset - FRU inventory offset to read
772 * @param readCount - count to read
773 *
774 * @return IPMI completion code plus response data
775 * - returnCount - response data count.
776 * - data - response data
777 */
778ipmi::RspType<uint8_t, // count returned
779 std::vector<uint8_t>> // FRU data
780 ipmiStorageReadFruData(uint8_t fruDeviceId, uint16_t offset,
781 uint8_t readCount)
Marri Devender Raofa7b4e22017-07-03 00:52:20 -0500782{
anil kumar appana5b7c3262019-05-27 18:10:23 +0000783 if (fruDeviceId == 0xFF)
Tom Joseph187f5642018-03-29 13:49:06 +0530784 {
anil kumar appana5b7c3262019-05-27 18:10:23 +0000785 return ipmi::responseInvalidFieldRequest();
Tom Joseph187f5642018-03-29 13:49:06 +0530786 }
787
anil kumar appana5b7c3262019-05-27 18:10:23 +0000788 auto iter = frus.find(fruDeviceId);
789 if (iter == frus.end())
790 {
791 return ipmi::responseSensorInvalid();
792 }
793
Marri Devender Raocac383b2017-07-03 13:24:27 -0500794 try
795 {
anil kumar appana5b7c3262019-05-27 18:10:23 +0000796 const auto& fruArea = getFruAreaData(fruDeviceId);
Marri Devender Raocac383b2017-07-03 13:24:27 -0500797 auto size = fruArea.size();
Nagaraju Goruganti7f2d7c92018-03-21 11:18:30 -0500798
Tom Josephefcd68b2018-04-26 18:46:27 +0530799 if (offset >= size)
800 {
anil kumar appana5b7c3262019-05-27 18:10:23 +0000801 return ipmi::responseParmOutOfRange();
Tom Josephefcd68b2018-04-26 18:46:27 +0530802 }
803
Nagaraju Goruganti7f2d7c92018-03-21 11:18:30 -0500804 // Write the count of response data.
anil kumar appana5b7c3262019-05-27 18:10:23 +0000805 uint8_t returnCount;
806 if ((offset + readCount) <= size)
Marri Devender Raocac383b2017-07-03 13:24:27 -0500807 {
anil kumar appana5b7c3262019-05-27 18:10:23 +0000808 returnCount = readCount;
Nagaraju Goruganti7f2d7c92018-03-21 11:18:30 -0500809 }
810 else
811 {
anil kumar appana5b7c3262019-05-27 18:10:23 +0000812 returnCount = size - offset;
Marri Devender Raocac383b2017-07-03 13:24:27 -0500813 }
Ratan Gupta2848d602018-01-31 20:39:20 +0530814
anil kumar appana5b7c3262019-05-27 18:10:23 +0000815 std::vector<uint8_t> fruData((fruArea.begin() + offset),
816 (fruArea.begin() + offset + returnCount));
Ratan Gupta2848d602018-01-31 20:39:20 +0530817
anil kumar appana5b7c3262019-05-27 18:10:23 +0000818 return ipmi::responseSuccess(returnCount, fruData);
Marri Devender Raocac383b2017-07-03 13:24:27 -0500819 }
820 catch (const InternalFailure& e)
821 {
Marri Devender Raocac383b2017-07-03 13:24:27 -0500822 log<level::ERR>(e.what());
anil kumar appana5b7c3262019-05-27 18:10:23 +0000823 return ipmi::responseUnspecifiedError();
Marri Devender Raocac383b2017-07-03 13:24:27 -0500824 }
Marri Devender Raofa7b4e22017-07-03 00:52:20 -0500825}
826
Pradeep Kumarb60e8402019-05-06 15:17:01 +0000827ipmi::RspType<uint8_t, // SDR version
828 uint16_t, // record count LS first
829 uint16_t, // free space in bytes, LS first
830 uint32_t, // addition timestamp LS first
831 uint32_t, // deletion timestamp LS first
832 uint8_t> // operation Support
833 ipmiGetRepositoryInfo()
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600834{
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600835
Pradeep Kumarb60e8402019-05-06 15:17:01 +0000836 constexpr uint8_t sdrVersion = 0x51;
837 constexpr uint16_t freeSpace = 0xFFFF;
838 constexpr uint32_t additionTimestamp = 0x0;
839 constexpr uint32_t deletionTimestamp = 0x0;
840 constexpr uint8_t operationSupport = 0;
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600841
Patrick Venturedb0cbe62019-09-09 14:47:22 -0700842 uint16_t records = frus.size() + ipmi::sensor::sensors.size();
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600843
Pradeep Kumarb60e8402019-05-06 15:17:01 +0000844 return ipmi::responseSuccess(sdrVersion, records, freeSpace,
845 additionTimestamp, deletionTimestamp,
846 operationSupport);
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600847}
Chris Austenb4f5b922015-10-13 12:44:43 -0500848
Chris Austenb4f5b922015-10-13 12:44:43 -0500849void register_netfn_storage_functions()
850{
Lei YUd9e57662021-09-14 18:06:28 +0800851 initSELCache();
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530852 // <Get SEL Info>
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000853 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
854 ipmi::storage::cmdGetSelInfo, ipmi::Privilege::User,
855 ipmiStorageGetSelInfo);
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530856
Tom05732372016-09-06 17:21:23 +0530857 // <Get SEL Time>
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000858 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
859 ipmi::storage::cmdGetSelTime, ipmi::Privilege::User,
860 ipmiStorageGetSelTime);
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500861
Tom05732372016-09-06 17:21:23 +0530862 // <Set SEL Time>
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000863 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
864 ipmi::storage::cmdSetSelTime,
865 ipmi::Privilege::Operator, ipmiStorageSetSelTime);
Chris Austenb4f5b922015-10-13 12:44:43 -0500866
Tom05732372016-09-06 17:21:23 +0530867 // <Reserve SEL>
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000868 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
869 ipmi::storage::cmdReserveSel, ipmi::Privilege::User,
870 ipmiStorageReserveSel);
Tom Josepha4953392017-06-30 19:09:47 +0530871 // <Get SEL Entry>
Patrick Venture0b02be92018-08-31 11:55:55 -0700872 ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SEL_ENTRY, NULL,
873 getSELEntry, PRIVILEGE_USER);
Tom Josepha4953392017-06-30 19:09:47 +0530874
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530875 // <Delete SEL Entry>
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000876 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
877 ipmi::storage::cmdDeleteSelEntry,
878 ipmi::Privilege::Operator, deleteSELEntry);
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530879
Tom05732372016-09-06 17:21:23 +0530880 // <Add SEL Entry>
anil kumar appana2c7db1d2019-05-28 11:20:19 +0000881 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
882 ipmi::storage::cmdAddSelEntry,
883 ipmi::Privilege::Operator, ipmiStorageAddSEL);
884
Tom Joseph2f05bb52017-06-30 19:14:49 +0530885 // <Clear SEL>
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000886 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
887 ipmi::storage::cmdClearSel, ipmi::Privilege::Operator,
888 clearSEL);
889
Marri Devender Raofa7b4e22017-07-03 00:52:20 -0500890 // <Get FRU Inventory Area Info>
Pradeep Kumarb0c794d2019-05-02 13:09:14 +0000891 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
892 ipmi::storage::cmdGetFruInventoryAreaInfo,
893 ipmi::Privilege::User, ipmiStorageGetFruInvAreaInfo);
Marri Devender Raofa7b4e22017-07-03 00:52:20 -0500894
Jason M. Billsb5248c92019-06-24 15:53:08 -0700895 // <READ FRU Data>
anil kumar appana5b7c3262019-05-27 18:10:23 +0000896 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
897 ipmi::storage::cmdReadFruData,
898 ipmi::Privilege::Operator, ipmiStorageReadFruData);
Marri Devender Raocac383b2017-07-03 13:24:27 -0500899
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600900 // <Get Repository Info>
Pradeep Kumarb60e8402019-05-06 15:17:01 +0000901 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
902 ipmi::storage::cmdGetSdrRepositoryInfo,
903 ipmi::Privilege::User, ipmiGetRepositoryInfo);
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600904
Tom Joseph5ca50952018-02-22 00:33:38 +0530905 // <Reserve SDR Repository>
jayaprakash Mutyalad9578232019-05-13 20:22:50 +0000906 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
907 ipmi::storage::cmdReserveSdrRepository,
908 ipmi::Privilege::User, ipmiSensorReserveSdr);
Tom Joseph5ca50952018-02-22 00:33:38 +0530909
910 // <Get SDR>
Patrick Venture0b02be92018-08-31 11:55:55 -0700911 ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SDR, nullptr,
912 ipmi_sen_get_sdr, PRIVILEGE_USER);
Tom Joseph5ca50952018-02-22 00:33:38 +0530913
Marri Devender Rao908f7502017-07-10 01:49:54 -0500914 ipmi::fru::registerCallbackHandler();
Chris Austenb4f5b922015-10-13 12:44:43 -0500915 return;
916}