blob: fdd5ffb5770763d0e53172196e552ae771a82066 [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 YUd9e57662021-09-14 18:06:28 +080047constexpr auto logBasePath = "/xyz/openbmc_project/logging/entry";
48constexpr auto logEntryIntf = "xyz.openbmc_project.Logging.Entry";
49constexpr auto logDeleteIntf = "xyz.openbmc_project.Object.Delete";
Patrick Venture0b02be92018-08-31 11:55:55 -070050} // namespace
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +053051
Tom Joseph6f7deaa2017-06-30 19:03:54 +053052namespace cache
53{
Patrick Venture0b02be92018-08-31 11:55:55 -070054/*
55 * This cache contains the object paths of the logging entries sorted in the
56 * order of the filename(numeric order). The cache is initialized by
57 * invoking readLoggingObjectPaths with the cache as the parameter. The
58 * cache is invoked in the execution of the Get SEL info and Delete SEL
59 * entry command. The Get SEL Info command is typically invoked before the
60 * Get SEL entry command, so the cache is utilized for responding to Get SEL
61 * entry command. The cache is invalidated by clearing after Delete SEL
62 * entry and Clear SEL command.
63 */
64ipmi::sel::ObjectPaths paths;
Tom Joseph6f7deaa2017-06-30 19:03:54 +053065
Patrick Venture0b02be92018-08-31 11:55:55 -070066} // namespace cache
Tom Joseph6f7deaa2017-06-30 19:03:54 +053067
68using InternalFailure =
Patrick Venture0b02be92018-08-31 11:55:55 -070069 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Tom Joseph6f7deaa2017-06-30 19:03:54 +053070using namespace phosphor::logging;
Marri Devender Raocac383b2017-07-03 13:24:27 -050071using namespace ipmi::fru;
72
Lei YUd9e57662021-09-14 18:06:28 +080073using SELRecordID = uint16_t;
74using SELEntry = ipmi::sel::SELEventRecordFormat;
75using SELCacheMap = std::map<SELRecordID, SELEntry>;
76
77SELCacheMap selCacheMap __attribute__((init_priority(101)));
78
79std::pair<uint16_t, SELEntry> parseLoggingEntry(const std::string& p)
80{
81 namespace fs = std::filesystem;
82 fs::path entryPath(p);
83 auto id = static_cast<uint16_t>(std::stoul(entryPath.filename().string()));
84 // TODO: parse the sel data
85 return {id, {}};
86}
87
88void initSELCache()
89{
90 try
91 {
92 ipmi::sel::readLoggingObjectPaths(cache::paths);
93 }
94 catch (const sdbusplus::exception::exception& e)
95 {
96 log<level::ERR>("Failed to get logging object paths");
97 return;
98 }
99 for (const auto& p : cache::paths)
100 {
101 selCacheMap.insert(parseLoggingEntry(p));
102 }
103}
104
Marri Devender Raocac383b2017-07-03 13:24:27 -0500105/**
106 * @enum Device access mode
107 */
108enum class AccessMode
109{
110 bytes, ///< Device is accessed by bytes
111 words ///< Device is accessed by words
112};
113
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000114/** @brief implements the get SEL Info command
115 * @returns IPMI completion code plus response data
116 * - selVersion - SEL revision
117 * - entries - Number of log entries in SEL.
118 * - freeSpace - Free Space in bytes.
119 * - addTimeStamp - Most recent addition timestamp
120 * - eraseTimeStamp - Most recent erase timestamp
121 * - operationSupport - Reserve & Delete SEL operations supported
122 */
123
124ipmi::RspType<uint8_t, // SEL revision.
125 uint16_t, // number of log entries in SEL.
126 uint16_t, // free Space in bytes.
127 uint32_t, // most recent addition timestamp
128 uint32_t, // most recent erase timestamp.
129
130 bool, // SEL allocation info supported
131 bool, // reserve SEL supported
132 bool, // partial Add SEL Entry supported
133 bool, // delete SEL supported
134 uint3_t, // reserved
135 bool // overflow flag
136 >
137 ipmiStorageGetSelInfo()
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530138{
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000139 uint16_t entries = 0;
140 // Most recent addition timestamp.
141 uint32_t addTimeStamp = ipmi::sel::invalidTimeStamp;
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530142
Tom Josephe59abfb2018-08-06 18:46:27 +0530143 try
144 {
145 ipmi::sel::readLoggingObjectPaths(cache::paths);
146 }
Patrick Williamsef1259b2021-09-02 09:12:33 -0500147 catch (const sdbusplus::exception::exception& e)
Tom Josephe59abfb2018-08-06 18:46:27 +0530148 {
149 // No action if reading log objects have failed for this command.
150 // readLoggingObjectPaths will throw exception if there are no log
151 // entries. The command will be responded with number of SEL entries
152 // as 0.
153 }
154
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530155 if (!cache::paths.empty())
156 {
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000157 entries = static_cast<uint16_t>(cache::paths.size());
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530158
159 try
160 {
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000161 addTimeStamp = static_cast<uint32_t>(
Patrick Venture0b02be92018-08-31 11:55:55 -0700162 (ipmi::sel::getEntryTimeStamp(cache::paths.back()).count()));
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530163 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500164 catch (const InternalFailure& e)
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530165 {
166 }
167 catch (const std::runtime_error& e)
168 {
169 log<level::ERR>(e.what());
170 }
171 }
172
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000173 constexpr uint8_t selVersion = ipmi::sel::selVersion;
174 constexpr uint16_t freeSpace = 0xFFFF;
175 constexpr uint32_t eraseTimeStamp = ipmi::sel::invalidTimeStamp;
176 constexpr uint3_t reserved{0};
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530177
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000178 return ipmi::responseSuccess(
179 selVersion, entries, freeSpace, addTimeStamp, eraseTimeStamp,
180 ipmi::sel::operationSupport::getSelAllocationInfo,
181 ipmi::sel::operationSupport::reserveSel,
182 ipmi::sel::operationSupport::partialAddSelEntry,
183 ipmi::sel::operationSupport::deleteSel, reserved,
184 ipmi::sel::operationSupport::overflow);
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530185}
186
Tom Josepha4953392017-06-30 19:09:47 +0530187ipmi_ret_t getSELEntry(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
188 ipmi_request_t request, ipmi_response_t response,
189 ipmi_data_len_t data_len, ipmi_context_t context)
190{
Jason M. Bills851acb12019-02-04 14:06:57 -0800191 if (*data_len != sizeof(ipmi::sel::GetSELEntryRequest))
192 {
193 *data_len = 0;
194 return IPMI_CC_REQ_DATA_LEN_INVALID;
195 }
196
Patrick Venture0b02be92018-08-31 11:55:55 -0700197 auto requestData =
198 reinterpret_cast<const ipmi::sel::GetSELEntryRequest*>(request);
Tom Josepha4953392017-06-30 19:09:47 +0530199
200 if (requestData->reservationID != 0)
201 {
Jason M. Bills13e67c82018-09-10 14:12:16 -0700202 if (!checkSELReservation(requestData->reservationID))
Tom Josepha4953392017-06-30 19:09:47 +0530203 {
204 *data_len = 0;
205 return IPMI_CC_INVALID_RESERVATION_ID;
206 }
207 }
208
209 if (cache::paths.empty())
210 {
211 *data_len = 0;
212 return IPMI_CC_SENSOR_INVALID;
213 }
214
215 ipmi::sel::ObjectPaths::const_iterator iter;
216
217 // Check for the requested SEL Entry.
218 if (requestData->selRecordID == ipmi::sel::firstEntry)
219 {
220 iter = cache::paths.begin();
221 }
222 else if (requestData->selRecordID == ipmi::sel::lastEntry)
223 {
224 iter = cache::paths.end();
225 }
226 else
227 {
228 std::string objPath = std::string(ipmi::sel::logBasePath) + "/" +
229 std::to_string(requestData->selRecordID);
230
231 iter = std::find(cache::paths.begin(), cache::paths.end(), objPath);
232 if (iter == cache::paths.end())
233 {
234 *data_len = 0;
235 return IPMI_CC_SENSOR_INVALID;
236 }
237 }
238
Patrick Venture0b02be92018-08-31 11:55:55 -0700239 ipmi::sel::GetSELEntryResponse record{};
Tom Josepha4953392017-06-30 19:09:47 +0530240
241 // Convert the log entry into SEL record.
242 try
243 {
244 record = ipmi::sel::convertLogEntrytoSEL(*iter);
245 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500246 catch (const InternalFailure& e)
Tom Josepha4953392017-06-30 19:09:47 +0530247 {
248 *data_len = 0;
249 return IPMI_CC_UNSPECIFIED_ERROR;
250 }
251 catch (const std::runtime_error& e)
252 {
253 log<level::ERR>(e.what());
254 *data_len = 0;
255 return IPMI_CC_UNSPECIFIED_ERROR;
256 }
257
Tom Josepha4953392017-06-30 19:09:47 +0530258 // Identify the next SEL record ID
Patrick Venture0b02be92018-08-31 11:55:55 -0700259 if (iter != cache::paths.end())
Tom Josepha4953392017-06-30 19:09:47 +0530260 {
261 ++iter;
262 if (iter == cache::paths.end())
263 {
264 record.nextRecordID = ipmi::sel::lastEntry;
265 }
266 else
267 {
Vernon Mauery185b9f82018-07-20 10:52:36 -0700268 namespace fs = std::filesystem;
Tom Josepha4953392017-06-30 19:09:47 +0530269 fs::path path(*iter);
Patrick Venture0b02be92018-08-31 11:55:55 -0700270 record.nextRecordID = static_cast<uint16_t>(
271 std::stoul(std::string(path.filename().c_str())));
Tom Josepha4953392017-06-30 19:09:47 +0530272 }
273 }
274 else
275 {
276 record.nextRecordID = ipmi::sel::lastEntry;
277 }
278
279 if (requestData->readLength == ipmi::sel::entireRecord)
280 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700281 std::memcpy(response, &record, sizeof(record));
Tom Josepha4953392017-06-30 19:09:47 +0530282 *data_len = sizeof(record);
283 }
284 else
285 {
286 if (requestData->offset >= ipmi::sel::selRecordSize ||
287 requestData->readLength > ipmi::sel::selRecordSize)
288 {
289 *data_len = 0;
290 return IPMI_CC_INVALID_FIELD_REQUEST;
291 }
292
293 auto diff = ipmi::sel::selRecordSize - requestData->offset;
Patrick Venture0b02be92018-08-31 11:55:55 -0700294 auto readLength =
295 std::min(diff, static_cast<int>(requestData->readLength));
Tom Josepha4953392017-06-30 19:09:47 +0530296
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700297 std::memcpy(response, &record.nextRecordID,
298 sizeof(record.nextRecordID));
299 std::memcpy(static_cast<uint8_t*>(response) +
300 sizeof(record.nextRecordID),
Lei YUaf378fa2020-12-02 16:28:57 +0800301 &record.event.eventRecord.recordID + requestData->offset,
302 readLength);
Tom Josepha4953392017-06-30 19:09:47 +0530303 *data_len = sizeof(record.nextRecordID) + readLength;
304 }
305
306 return IPMI_CC_OK;
307}
308
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000309/** @brief implements the delete SEL entry command
310 * @request
311 * - reservationID; // reservation ID.
312 * - selRecordID; // SEL record ID.
313 *
314 * @returns ipmi completion code plus response data
315 * - Record ID of the deleted record
316 */
317ipmi::RspType<uint16_t // deleted record ID
318 >
319 deleteSELEntry(uint16_t reservationID, uint16_t selRecordID)
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530320{
Jason M. Bills851acb12019-02-04 14:06:57 -0800321
Brad Bishop1a4117b2018-11-21 15:48:18 -0500322 namespace fs = std::filesystem;
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530323
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000324 if (!checkSELReservation(reservationID))
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530325 {
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000326 return ipmi::responseInvalidReservationId();
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530327 }
328
Jason M. Bills13e67c82018-09-10 14:12:16 -0700329 // Per the IPMI spec, need to cancel the reservation when a SEL entry is
330 // deleted
331 cancelSELReservation();
332
Tom Josephe59abfb2018-08-06 18:46:27 +0530333 try
334 {
335 ipmi::sel::readLoggingObjectPaths(cache::paths);
336 }
Patrick Williamsef1259b2021-09-02 09:12:33 -0500337 catch (const sdbusplus::exception::exception& e)
Tom Josephe59abfb2018-08-06 18:46:27 +0530338 {
339 // readLoggingObjectPaths will throw exception if there are no error
340 // log entries.
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000341 return ipmi::responseSensorInvalid();
Tom Josephe59abfb2018-08-06 18:46:27 +0530342 }
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530343
344 if (cache::paths.empty())
345 {
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000346 return ipmi::responseSensorInvalid();
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530347 }
348
349 ipmi::sel::ObjectPaths::const_iterator iter;
350 uint16_t delRecordID = 0;
351
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000352 if (selRecordID == ipmi::sel::firstEntry)
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530353 {
354 iter = cache::paths.begin();
355 fs::path path(*iter);
Patrick Venture0b02be92018-08-31 11:55:55 -0700356 delRecordID = static_cast<uint16_t>(
357 std::stoul(std::string(path.filename().c_str())));
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530358 }
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000359 else if (selRecordID == ipmi::sel::lastEntry)
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530360 {
361 iter = cache::paths.end();
362 fs::path path(*iter);
Patrick Venture0b02be92018-08-31 11:55:55 -0700363 delRecordID = static_cast<uint16_t>(
364 std::stoul(std::string(path.filename().c_str())));
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530365 }
366 else
367 {
368 std::string objPath = std::string(ipmi::sel::logBasePath) + "/" +
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000369 std::to_string(selRecordID);
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530370
371 iter = std::find(cache::paths.begin(), cache::paths.end(), objPath);
372 if (iter == cache::paths.end())
373 {
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000374 return ipmi::responseSensorInvalid();
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530375 }
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000376 delRecordID = selRecordID;
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530377 }
378
379 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
380 std::string service;
381
382 try
383 {
384 service = ipmi::getService(bus, ipmi::sel::logDeleteIntf, *iter);
385 }
386 catch (const std::runtime_error& e)
387 {
388 log<level::ERR>(e.what());
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000389 return ipmi::responseUnspecifiedError();
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530390 }
391
Patrick Venture0b02be92018-08-31 11:55:55 -0700392 auto methodCall = bus.new_method_call(service.c_str(), (*iter).c_str(),
393 ipmi::sel::logDeleteIntf, "Delete");
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530394 auto reply = bus.call(methodCall);
395 if (reply.is_method_error())
396 {
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000397 return ipmi::responseUnspecifiedError();
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530398 }
399
400 // Invalidate the cache of dbus entry objects.
401 cache::paths.clear();
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530402
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000403 return ipmi::responseSuccess(delRecordID);
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530404}
405
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000406/** @brief implements the Clear SEL command
407 * @request
408 * - reservationID // Reservation ID.
409 * - clr // char array { 'C'(0x43h), 'L'(0x4Ch), 'R'(0x52h) }
410 * - eraseOperation; // requested operation.
411 *
412 * @returns ipmi completion code plus response data
413 * - erase status
414 */
415
416ipmi::RspType<uint8_t // erase status
417 >
418 clearSEL(uint16_t reservationID, const std::array<char, 3>& clr,
419 uint8_t eraseOperation)
Tom Joseph2f05bb52017-06-30 19:14:49 +0530420{
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000421 static constexpr std::array<char, 3> clrOk = {'C', 'L', 'R'};
422 if (clr != clrOk)
Jason M. Bills851acb12019-02-04 14:06:57 -0800423 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000424 return ipmi::responseInvalidFieldRequest();
Jason M. Bills851acb12019-02-04 14:06:57 -0800425 }
426
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000427 if (!checkSELReservation(reservationID))
Tom Joseph2f05bb52017-06-30 19:14:49 +0530428 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000429 return ipmi::responseInvalidReservationId();
Tom Joseph2f05bb52017-06-30 19:14:49 +0530430 }
431
Tom Joseph2f05bb52017-06-30 19:14:49 +0530432 /*
433 * Erasure status cannot be fetched from DBUS, so always return erasure
434 * status as `erase completed`.
435 */
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000436 if (eraseOperation == ipmi::sel::getEraseStatus)
Tom Joseph2f05bb52017-06-30 19:14:49 +0530437 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000438 return ipmi::responseSuccess(
439 static_cast<uint8_t>(ipmi::sel::eraseComplete));
Tom Joseph2f05bb52017-06-30 19:14:49 +0530440 }
441
Jason M. Bills13e67c82018-09-10 14:12:16 -0700442 // Per the IPMI spec, need to cancel any reservation when the SEL is cleared
443 cancelSELReservation();
444
Tom Joseph2f05bb52017-06-30 19:14:49 +0530445 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Tom Josephe59abfb2018-08-06 18:46:27 +0530446 ipmi::sel::ObjectPaths objectPaths;
Tom Joseph2f05bb52017-06-30 19:14:49 +0530447 auto depth = 0;
448
Patrick Venture0b02be92018-08-31 11:55:55 -0700449 auto mapperCall =
450 bus.new_method_call(ipmi::sel::mapperBusName, ipmi::sel::mapperObjPath,
451 ipmi::sel::mapperIntf, "GetSubTreePaths");
Tom Joseph2f05bb52017-06-30 19:14:49 +0530452 mapperCall.append(ipmi::sel::logBasePath);
453 mapperCall.append(depth);
454 mapperCall.append(ipmi::sel::ObjectPaths({ipmi::sel::logEntryIntf}));
455
Tom Josephe59abfb2018-08-06 18:46:27 +0530456 try
Tom Joseph2f05bb52017-06-30 19:14:49 +0530457 {
Tom Josephe59abfb2018-08-06 18:46:27 +0530458 auto reply = bus.call(mapperCall);
459 if (reply.is_method_error())
460 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000461 return ipmi::responseSuccess(
462 static_cast<uint8_t>(ipmi::sel::eraseComplete));
Tom Josephe59abfb2018-08-06 18:46:27 +0530463 }
Tom Joseph2f05bb52017-06-30 19:14:49 +0530464
Tom Josephe59abfb2018-08-06 18:46:27 +0530465 reply.read(objectPaths);
466 if (objectPaths.empty())
467 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000468 return ipmi::responseSuccess(
469 static_cast<uint8_t>(ipmi::sel::eraseComplete));
Tom Josephe59abfb2018-08-06 18:46:27 +0530470 }
471 }
Patrick Williamsef1259b2021-09-02 09:12:33 -0500472 catch (const sdbusplus::exception::exception& e)
Tom Joseph2f05bb52017-06-30 19:14:49 +0530473 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000474 return ipmi::responseSuccess(
475 static_cast<uint8_t>(ipmi::sel::eraseComplete));
Tom Joseph2f05bb52017-06-30 19:14:49 +0530476 }
477
478 std::string service;
479
480 try
481 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700482 service = ipmi::getService(bus, ipmi::sel::logDeleteIntf,
Tom Joseph2f05bb52017-06-30 19:14:49 +0530483 objectPaths.front());
484 }
485 catch (const std::runtime_error& e)
486 {
487 log<level::ERR>(e.what());
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000488 return ipmi::responseUnspecifiedError();
Tom Joseph2f05bb52017-06-30 19:14:49 +0530489 }
490
491 for (const auto& iter : objectPaths)
492 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700493 auto methodCall = bus.new_method_call(
494 service.c_str(), iter.c_str(), ipmi::sel::logDeleteIntf, "Delete");
Tom Joseph2f05bb52017-06-30 19:14:49 +0530495
496 auto reply = bus.call(methodCall);
497 if (reply.is_method_error())
498 {
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000499 return ipmi::responseUnspecifiedError();
Tom Joseph2f05bb52017-06-30 19:14:49 +0530500 }
501 }
502
503 // Invalidate the cache of dbus entry objects.
504 cache::paths.clear();
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000505 return ipmi::responseSuccess(
506 static_cast<uint8_t>(ipmi::sel::eraseComplete));
Tom Joseph2f05bb52017-06-30 19:14:49 +0530507}
508
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000509/** @brief implements the get SEL time command
510 * @returns IPMI completion code plus response data
511 * -current time
512 */
513ipmi::RspType<uint32_t> // current time
514 ipmiStorageGetSelTime()
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500515{
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530516 using namespace std::chrono;
George Liu4d623e92020-05-25 16:51:57 +0800517 uint64_t bmc_time_usec = 0;
518 std::stringstream bmcTime;
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500519
Lei YUe8939392017-06-15 10:45:05 +0800520 try
521 {
522 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
George Liu4d623e92020-05-25 16:51:57 +0800523 auto service = ipmi::getService(bus, TIME_INTERFACE, BMC_TIME_PATH);
Vernon Mauery16b86932019-05-01 08:36:11 -0700524 std::variant<uint64_t> value;
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530525
George Liu4d623e92020-05-25 16:51:57 +0800526 // Get bmc time
527 auto method = bus.new_method_call(service.c_str(), BMC_TIME_PATH,
Patrick Venture0b02be92018-08-31 11:55:55 -0700528 DBUS_PROPERTIES, "Get");
Lei YUe8939392017-06-15 10:45:05 +0800529
530 method.append(TIME_INTERFACE, PROPERTY_ELAPSED);
531 auto reply = bus.call(method);
532 if (reply.is_method_error())
533 {
534 log<level::ERR>("Error getting time",
535 entry("SERVICE=%s", service.c_str()),
George Liu4d623e92020-05-25 16:51:57 +0800536 entry("PATH=%s", BMC_TIME_PATH));
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000537 return ipmi::responseUnspecifiedError();
Lei YUe8939392017-06-15 10:45:05 +0800538 }
539 reply.read(value);
George Liu4d623e92020-05-25 16:51:57 +0800540 bmc_time_usec = std::get<uint64_t>(value);
Lei YUe8939392017-06-15 10:45:05 +0800541 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500542 catch (const InternalFailure& e)
Lei YUe8939392017-06-15 10:45:05 +0800543 {
544 log<level::ERR>(e.what());
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000545 return ipmi::responseUnspecifiedError();
Lei YUe8939392017-06-15 10:45:05 +0800546 }
Tom Joseph30fd0a12019-09-24 06:53:22 +0530547 catch (const std::exception& e)
Lei YUe8939392017-06-15 10:45:05 +0800548 {
549 log<level::ERR>(e.what());
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000550 return ipmi::responseUnspecifiedError();
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530551 }
552
George Liu4d623e92020-05-25 16:51:57 +0800553 bmcTime << "BMC time:"
554 << duration_cast<seconds>(microseconds(bmc_time_usec)).count();
555 log<level::DEBUG>(bmcTime.str().c_str());
Nagaraju Goruganti8960b7c2018-04-29 22:38:40 -0500556
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530557 // Time is really long int but IPMI wants just uint32. This works okay until
558 // the number of seconds since 1970 overflows uint32 size.. Still a whole
559 // lot of time here to even think about that.
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000560 return ipmi::responseSuccess(
George Liu4d623e92020-05-25 16:51:57 +0800561 duration_cast<seconds>(microseconds(bmc_time_usec)).count());
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500562}
563
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000564/** @brief implements the set SEL time command
565 * @param selDeviceTime - epoch time
566 * -local time as the number of seconds from 00:00:00, January 1, 1970
567 * @returns IPMI completion code
568 */
569ipmi::RspType<> ipmiStorageSetSelTime(uint32_t selDeviceTime)
Chris Austenb4f5b922015-10-13 12:44:43 -0500570{
Lei YUe8939392017-06-15 10:45:05 +0800571 using namespace std::chrono;
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000572 microseconds usec{seconds(selDeviceTime)};
Norman James82330442015-11-19 16:53:26 -0600573
Lei YUe8939392017-06-15 10:45:05 +0800574 try
575 {
576 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
George Liu4d623e92020-05-25 16:51:57 +0800577 auto service = ipmi::getService(bus, TIME_INTERFACE, BMC_TIME_PATH);
Andrew Geissler6467ed22020-05-16 16:03:53 -0500578 std::variant<uint64_t> value{(uint64_t)usec.count()};
Lei YUe8939392017-06-15 10:45:05 +0800579
George Liu4d623e92020-05-25 16:51:57 +0800580 // Set bmc time
581 auto method = bus.new_method_call(service.c_str(), BMC_TIME_PATH,
Patrick Venture0b02be92018-08-31 11:55:55 -0700582 DBUS_PROPERTIES, "Set");
Lei YUe8939392017-06-15 10:45:05 +0800583
584 method.append(TIME_INTERFACE, PROPERTY_ELAPSED, value);
585 auto reply = bus.call(method);
586 if (reply.is_method_error())
587 {
588 log<level::ERR>("Error setting time",
589 entry("SERVICE=%s", service.c_str()),
George Liu4d623e92020-05-25 16:51:57 +0800590 entry("PATH=%s", BMC_TIME_PATH));
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000591 return ipmi::responseUnspecifiedError();
Lei YUe8939392017-06-15 10:45:05 +0800592 }
Norman James82330442015-11-19 16:53:26 -0600593 }
Patrick Williamsa2ad2da2021-10-06 12:21:46 -0500594 catch (const InternalFailure& e)
Lei YUe8939392017-06-15 10:45:05 +0800595 {
596 log<level::ERR>(e.what());
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000597 return ipmi::responseUnspecifiedError();
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530598 }
Tom Joseph30fd0a12019-09-24 06:53:22 +0530599 catch (const std::exception& e)
Lei YUe8939392017-06-15 10:45:05 +0800600 {
601 log<level::ERR>(e.what());
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000602 return ipmi::responseUnspecifiedError();
Norman James82330442015-11-19 16:53:26 -0600603 }
Vishwanatha Subbanna5fba7a62016-09-01 14:06:07 +0530604
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000605 return ipmi::responseSuccess();
Chris Austenb4f5b922015-10-13 12:44:43 -0500606}
607
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000608/** @brief implements the reserve SEL command
609 * @returns IPMI completion code plus response data
610 * - SEL reservation ID.
611 */
612ipmi::RspType<uint16_t> ipmiStorageReserveSel()
Chris Austenb4f5b922015-10-13 12:44:43 -0500613{
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000614 return ipmi::responseSuccess(reserveSel());
Chris Austenb4f5b922015-10-13 12:44:43 -0500615}
616
anil kumar appana2c7db1d2019-05-28 11:20:19 +0000617/** @brief implements the Add SEL entry command
618 * @request
619 *
620 * - recordID ID used for SEL Record access
621 * - recordType Record Type
622 * - timeStamp Time when event was logged. LS byte first
623 * - generatorID software ID if event was generated from
624 * system software
625 * - evmRev event message format version
626 * - sensorType sensor type code for service that generated
627 * the event
628 * - sensorNumber number of sensors that generated the event
629 * - eventDir event dir
630 * - eventData event data field contents
631 *
632 * @returns ipmi completion code plus response data
633 * - RecordID of the Added SEL entry
634 */
635ipmi::RspType<uint16_t // recordID of the Added SEL entry
636 >
637 ipmiStorageAddSEL(uint16_t recordID, uint8_t recordType, uint32_t timeStamp,
638 uint16_t generatorID, uint8_t evmRev, uint8_t sensorType,
639 uint8_t sensorNumber, uint8_t eventDir,
640 std::array<uint8_t, eventDataSize> eventData)
Chris Austenb4f5b922015-10-13 12:44:43 -0500641{
Jason M. Bills13e67c82018-09-10 14:12:16 -0700642 // Per the IPMI spec, need to cancel the reservation when a SEL entry is
643 // added
644 cancelSELReservation();
Tom Josephb647d5b2017-10-31 17:25:33 +0530645 // Hostboot sends SEL with OEM record type 0xDE to indicate that there is
646 // a maintenance procedure associated with eSEL record.
647 static constexpr auto procedureType = 0xDE;
anil kumar appana2c7db1d2019-05-28 11:20:19 +0000648 if (recordType == procedureType)
Tom Josephb647d5b2017-10-31 17:25:33 +0530649 {
650 // In the OEM record type 0xDE, byte 11 in the SEL record indicate the
651 // procedure number.
anil kumar appana2c7db1d2019-05-28 11:20:19 +0000652 createProcedureLogEntry(sensorType);
Tom Josephb647d5b2017-10-31 17:25:33 +0530653 }
Chris Austenb4f5b922015-10-13 12:44:43 -0500654
anil kumar appana2c7db1d2019-05-28 11:20:19 +0000655 return ipmi::responseSuccess(recordID);
Chris Austenb4f5b922015-10-13 12:44:43 -0500656}
657
Kirill Pakhomovfa6e2092020-04-24 18:57:15 +0300658bool isFruPresent(const std::string& fruPath)
659{
660 using namespace ipmi::fru;
661
662 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
663
664 auto propValue =
665 ipmi::getDbusProperty(bus, invMgrInterface, invObjPath + fruPath,
666 invItemInterface, itemPresentProp);
667
668 return std::get<bool>(propValue);
669}
670
Pradeep Kumarb0c794d2019-05-02 13:09:14 +0000671/** @brief implements the get FRU Inventory Area Info command
672 *
673 * @returns IPMI completion code plus response data
674 * - FRU Inventory area size in bytes,
675 * - access bit
676 **/
677ipmi::RspType<uint16_t, // FRU Inventory area size in bytes,
678 uint8_t // access size (bytes / words)
679 >
680 ipmiStorageGetFruInvAreaInfo(uint8_t fruID)
Marri Devender Raofa7b4e22017-07-03 00:52:20 -0500681{
Tom Joseph187f5642018-03-29 13:49:06 +0530682
Pradeep Kumarb0c794d2019-05-02 13:09:14 +0000683 auto iter = frus.find(fruID);
Tom Joseph187f5642018-03-29 13:49:06 +0530684 if (iter == frus.end())
685 {
Pradeep Kumarb0c794d2019-05-02 13:09:14 +0000686 return ipmi::responseSensorInvalid();
Tom Joseph187f5642018-03-29 13:49:06 +0530687 }
688
Kirill Pakhomovfa6e2092020-04-24 18:57:15 +0300689 auto path = iter->second[0].path;
690 if (!isFruPresent(path))
691 {
692 return ipmi::responseSensorInvalid();
693 }
694
Marri Devender Raocac383b2017-07-03 13:24:27 -0500695 try
696 {
Pradeep Kumarb0c794d2019-05-02 13:09:14 +0000697 return ipmi::responseSuccess(
698 static_cast<uint16_t>(getFruAreaData(fruID).size()),
699 static_cast<uint8_t>(AccessMode::bytes));
Marri Devender Raocac383b2017-07-03 13:24:27 -0500700 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700701 catch (const InternalFailure& e)
Marri Devender Raocac383b2017-07-03 13:24:27 -0500702 {
Marri Devender Raocac383b2017-07-03 13:24:27 -0500703 log<level::ERR>(e.what());
Pradeep Kumarb0c794d2019-05-02 13:09:14 +0000704 return ipmi::responseUnspecifiedError();
Marri Devender Raocac383b2017-07-03 13:24:27 -0500705 }
Marri Devender Raofa7b4e22017-07-03 00:52:20 -0500706}
707
anil kumar appana5b7c3262019-05-27 18:10:23 +0000708/**@brief implements the Read FRU Data command
709 * @param fruDeviceId - FRU device ID. FFh = reserved
710 * @param offset - FRU inventory offset to read
711 * @param readCount - count to read
712 *
713 * @return IPMI completion code plus response data
714 * - returnCount - response data count.
715 * - data - response data
716 */
717ipmi::RspType<uint8_t, // count returned
718 std::vector<uint8_t>> // FRU data
719 ipmiStorageReadFruData(uint8_t fruDeviceId, uint16_t offset,
720 uint8_t readCount)
Marri Devender Raofa7b4e22017-07-03 00:52:20 -0500721{
anil kumar appana5b7c3262019-05-27 18:10:23 +0000722 if (fruDeviceId == 0xFF)
Tom Joseph187f5642018-03-29 13:49:06 +0530723 {
anil kumar appana5b7c3262019-05-27 18:10:23 +0000724 return ipmi::responseInvalidFieldRequest();
Tom Joseph187f5642018-03-29 13:49:06 +0530725 }
726
anil kumar appana5b7c3262019-05-27 18:10:23 +0000727 auto iter = frus.find(fruDeviceId);
728 if (iter == frus.end())
729 {
730 return ipmi::responseSensorInvalid();
731 }
732
Marri Devender Raocac383b2017-07-03 13:24:27 -0500733 try
734 {
anil kumar appana5b7c3262019-05-27 18:10:23 +0000735 const auto& fruArea = getFruAreaData(fruDeviceId);
Marri Devender Raocac383b2017-07-03 13:24:27 -0500736 auto size = fruArea.size();
Nagaraju Goruganti7f2d7c92018-03-21 11:18:30 -0500737
Tom Josephefcd68b2018-04-26 18:46:27 +0530738 if (offset >= size)
739 {
anil kumar appana5b7c3262019-05-27 18:10:23 +0000740 return ipmi::responseParmOutOfRange();
Tom Josephefcd68b2018-04-26 18:46:27 +0530741 }
742
Nagaraju Goruganti7f2d7c92018-03-21 11:18:30 -0500743 // Write the count of response data.
anil kumar appana5b7c3262019-05-27 18:10:23 +0000744 uint8_t returnCount;
745 if ((offset + readCount) <= size)
Marri Devender Raocac383b2017-07-03 13:24:27 -0500746 {
anil kumar appana5b7c3262019-05-27 18:10:23 +0000747 returnCount = readCount;
Nagaraju Goruganti7f2d7c92018-03-21 11:18:30 -0500748 }
749 else
750 {
anil kumar appana5b7c3262019-05-27 18:10:23 +0000751 returnCount = size - offset;
Marri Devender Raocac383b2017-07-03 13:24:27 -0500752 }
Ratan Gupta2848d602018-01-31 20:39:20 +0530753
anil kumar appana5b7c3262019-05-27 18:10:23 +0000754 std::vector<uint8_t> fruData((fruArea.begin() + offset),
755 (fruArea.begin() + offset + returnCount));
Ratan Gupta2848d602018-01-31 20:39:20 +0530756
anil kumar appana5b7c3262019-05-27 18:10:23 +0000757 return ipmi::responseSuccess(returnCount, fruData);
Marri Devender Raocac383b2017-07-03 13:24:27 -0500758 }
759 catch (const InternalFailure& e)
760 {
Marri Devender Raocac383b2017-07-03 13:24:27 -0500761 log<level::ERR>(e.what());
anil kumar appana5b7c3262019-05-27 18:10:23 +0000762 return ipmi::responseUnspecifiedError();
Marri Devender Raocac383b2017-07-03 13:24:27 -0500763 }
Marri Devender Raofa7b4e22017-07-03 00:52:20 -0500764}
765
Pradeep Kumarb60e8402019-05-06 15:17:01 +0000766ipmi::RspType<uint8_t, // SDR version
767 uint16_t, // record count LS first
768 uint16_t, // free space in bytes, LS first
769 uint32_t, // addition timestamp LS first
770 uint32_t, // deletion timestamp LS first
771 uint8_t> // operation Support
772 ipmiGetRepositoryInfo()
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600773{
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600774
Pradeep Kumarb60e8402019-05-06 15:17:01 +0000775 constexpr uint8_t sdrVersion = 0x51;
776 constexpr uint16_t freeSpace = 0xFFFF;
777 constexpr uint32_t additionTimestamp = 0x0;
778 constexpr uint32_t deletionTimestamp = 0x0;
779 constexpr uint8_t operationSupport = 0;
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600780
Patrick Venturedb0cbe62019-09-09 14:47:22 -0700781 uint16_t records = frus.size() + ipmi::sensor::sensors.size();
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600782
Pradeep Kumarb60e8402019-05-06 15:17:01 +0000783 return ipmi::responseSuccess(sdrVersion, records, freeSpace,
784 additionTimestamp, deletionTimestamp,
785 operationSupport);
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600786}
Chris Austenb4f5b922015-10-13 12:44:43 -0500787
Chris Austenb4f5b922015-10-13 12:44:43 -0500788void register_netfn_storage_functions()
789{
Lei YUd9e57662021-09-14 18:06:28 +0800790 initSELCache();
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530791 // <Get SEL Info>
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000792 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
793 ipmi::storage::cmdGetSelInfo, ipmi::Privilege::User,
794 ipmiStorageGetSelInfo);
Tom Joseph6f7deaa2017-06-30 19:03:54 +0530795
Tom05732372016-09-06 17:21:23 +0530796 // <Get SEL Time>
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000797 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
798 ipmi::storage::cmdGetSelTime, ipmi::Privilege::User,
799 ipmiStorageGetSelTime);
Adriana Kobylak8e30f2a2015-10-20 10:23:51 -0500800
Tom05732372016-09-06 17:21:23 +0530801 // <Set SEL Time>
jayaprakash Mutyaladb2e8c42019-05-03 01:38:01 +0000802 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
803 ipmi::storage::cmdSetSelTime,
804 ipmi::Privilege::Operator, ipmiStorageSetSelTime);
Chris Austenb4f5b922015-10-13 12:44:43 -0500805
Tom05732372016-09-06 17:21:23 +0530806 // <Reserve SEL>
jayaprakash Mutyalab7557722019-05-02 21:13:30 +0000807 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
808 ipmi::storage::cmdReserveSel, ipmi::Privilege::User,
809 ipmiStorageReserveSel);
Tom Josepha4953392017-06-30 19:09:47 +0530810 // <Get SEL Entry>
Patrick Venture0b02be92018-08-31 11:55:55 -0700811 ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SEL_ENTRY, NULL,
812 getSELEntry, PRIVILEGE_USER);
Tom Josepha4953392017-06-30 19:09:47 +0530813
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530814 // <Delete SEL Entry>
Pradeep Kumar00a18d02019-04-26 17:04:28 +0000815 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
816 ipmi::storage::cmdDeleteSelEntry,
817 ipmi::Privilege::Operator, deleteSELEntry);
Tom Joseph8f4a2aa2017-06-30 19:12:49 +0530818
Tom05732372016-09-06 17:21:23 +0530819 // <Add SEL Entry>
anil kumar appana2c7db1d2019-05-28 11:20:19 +0000820 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
821 ipmi::storage::cmdAddSelEntry,
822 ipmi::Privilege::Operator, ipmiStorageAddSEL);
823
Tom Joseph2f05bb52017-06-30 19:14:49 +0530824 // <Clear SEL>
Pradeep Kumar4a5a99a2019-04-26 15:22:39 +0000825 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
826 ipmi::storage::cmdClearSel, ipmi::Privilege::Operator,
827 clearSEL);
828
Marri Devender Raofa7b4e22017-07-03 00:52:20 -0500829 // <Get FRU Inventory Area Info>
Pradeep Kumarb0c794d2019-05-02 13:09:14 +0000830 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
831 ipmi::storage::cmdGetFruInventoryAreaInfo,
832 ipmi::Privilege::User, ipmiStorageGetFruInvAreaInfo);
Marri Devender Raofa7b4e22017-07-03 00:52:20 -0500833
Jason M. Billsb5248c92019-06-24 15:53:08 -0700834 // <READ FRU Data>
anil kumar appana5b7c3262019-05-27 18:10:23 +0000835 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
836 ipmi::storage::cmdReadFruData,
837 ipmi::Privilege::Operator, ipmiStorageReadFruData);
Marri Devender Raocac383b2017-07-03 13:24:27 -0500838
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600839 // <Get Repository Info>
Pradeep Kumarb60e8402019-05-06 15:17:01 +0000840 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
841 ipmi::storage::cmdGetSdrRepositoryInfo,
842 ipmi::Privilege::User, ipmiGetRepositoryInfo);
Dhruvaraj Subhashchandrane66c3b02018-02-07 01:21:56 -0600843
Tom Joseph5ca50952018-02-22 00:33:38 +0530844 // <Reserve SDR Repository>
jayaprakash Mutyalad9578232019-05-13 20:22:50 +0000845 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
846 ipmi::storage::cmdReserveSdrRepository,
847 ipmi::Privilege::User, ipmiSensorReserveSdr);
Tom Joseph5ca50952018-02-22 00:33:38 +0530848
849 // <Get SDR>
Patrick Venture0b02be92018-08-31 11:55:55 -0700850 ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SDR, nullptr,
851 ipmi_sen_get_sdr, PRIVILEGE_USER);
Tom Joseph5ca50952018-02-22 00:33:38 +0530852
Marri Devender Rao908f7502017-07-10 01:49:54 -0500853 ipmi::fru::registerCallbackHandler();
Chris Austenb4f5b922015-10-13 12:44:43 -0500854 return;
855}