blob: e21a738f99c800957fc943c3e8ba3ced24cc631f [file] [log] [blame]
Vernon Mauerya3702c12019-05-22 13:20:59 -07001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
Yong Lic3580e92019-08-15 14:36:47 +080017#include <bitset>
Vernon Mauerya3702c12019-05-22 13:20:59 -070018#include <bridgingcommands.hpp>
19#include <cstring>
Vernon Mauery15419dd2019-05-24 09:40:30 -070020#include <ipmid/api.hpp>
Yong Lic3580e92019-08-15 14:36:47 +080021#include <ipmid/utils.hpp>
Yong Liedbb4082020-03-06 17:38:25 +080022#include <manufacturingcommands.hpp>
Vernon Mauerya3702c12019-05-22 13:20:59 -070023#include <phosphor-logging/log.hpp>
24#include <sdbusplus/bus.hpp>
25#include <sdbusplus/bus/match.hpp>
26#include <sdbusplus/message.hpp>
jayaprakash Mutyala5ba46872019-11-20 00:02:48 +000027#include <storagecommands.hpp>
Vernon Mauerya3702c12019-05-22 13:20:59 -070028#include <vector>
29
Yong Lic3580e92019-08-15 14:36:47 +080030static constexpr const char *wdtService = "xyz.openbmc_project.Watchdog";
31static constexpr const char *wdtInterface =
32 "xyz.openbmc_project.State.Watchdog";
33static constexpr const char *wdtObjPath = "/xyz/openbmc_project/watchdog/host0";
34static constexpr const char *wdtInterruptFlagProp =
35 "PreTimeoutInterruptOccurFlag";
36
Vernon Mauerya3702c12019-05-22 13:20:59 -070037static constexpr const char *ipmbBus = "xyz.openbmc_project.Ipmi.Channel.Ipmb";
38static constexpr const char *ipmbObj = "/xyz/openbmc_project/Ipmi/Channel/Ipmb";
39static constexpr const char *ipmbIntf = "org.openbmc.Ipmb";
40
41static Bridging bridging;
jayaprakash Mutyala5ba46872019-11-20 00:02:48 +000042static bool eventMessageBufferFlag = false;
Vernon Mauerya3702c12019-05-22 13:20:59 -070043
jayaprakash Mutyala405f54a2019-10-18 18:23:27 +000044void Bridging::clearResponseQueue()
45{
46 responseQueue.clear();
47}
48
Vernon Mauerya3702c12019-05-22 13:20:59 -070049/**
50 * @brief utils for checksum
51 */
52static bool ipmbChecksumValidate(uint8_t *data, uint8_t length)
53{
54 if (data == nullptr)
55 {
56 return false;
57 }
58
59 uint8_t checksum = 0;
60
61 for (uint8_t idx = 0; idx < length; idx++)
62 {
63 checksum += data[idx];
64 }
65
66 if (0 == checksum)
67 {
68 return true;
69 }
70
71 return false;
72}
73
74static uint8_t ipmbChecksumCompute(uint8_t *data, uint8_t length)
75{
76 if (data == nullptr)
77 {
78 return 0;
79 }
80
81 uint8_t checksum = 0;
82
83 for (uint8_t idx = 0; idx < length; idx++)
84 {
85 checksum += data[idx];
86 }
87
88 checksum = (~checksum) + 1;
89 return checksum;
90}
91
92static inline bool ipmbConnectionHeaderChecksumValidate(ipmbHeader *ipmbHeader)
93{
94 return ipmbChecksumValidate(reinterpret_cast<uint8_t *>(ipmbHeader),
95 ipmbConnectionHeaderLength);
96}
97
98static inline bool ipmbDataChecksumValidate(ipmbHeader *ipmbHeader,
99 uint8_t length)
100{
101 return ipmbChecksumValidate(
102 (reinterpret_cast<uint8_t *>(ipmbHeader) + ipmbConnectionHeaderLength),
103 (length - ipmbConnectionHeaderLength));
104}
105
106static bool isFrameValid(ipmbHeader *frame, uint8_t length)
107{
108 if ((length < ipmbMinFrameLength) || (length > ipmbMaxFrameLength))
109 {
110 return false;
111 }
112
113 if (false == ipmbConnectionHeaderChecksumValidate(frame))
114 {
115 return false;
116 }
117
118 if (false == ipmbDataChecksumValidate(frame, length))
119 {
120 return false;
121 }
122
123 return true;
124}
125
126IpmbRequest::IpmbRequest(const ipmbHeader *ipmbBuffer, size_t bufferLength)
127{
128 address = ipmbBuffer->Header.Req.address;
129 netFn = ipmbNetFnGet(ipmbBuffer->Header.Req.rsNetFnLUN);
130 rsLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Req.rsNetFnLUN);
131 rqSA = ipmbBuffer->Header.Req.rqSA;
132 seq = ipmbSeqGet(ipmbBuffer->Header.Req.rqSeqLUN);
133 rqLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Req.rqSeqLUN);
134 cmd = ipmbBuffer->Header.Req.cmd;
135
136 size_t dataLength =
137 bufferLength - (ipmbConnectionHeaderLength +
138 ipmbRequestDataHeaderLength + ipmbChecksumSize);
139
140 if (dataLength > 0)
141 {
142 data.insert(data.end(), ipmbBuffer->Header.Req.data,
143 &ipmbBuffer->Header.Req.data[dataLength]);
144 }
145}
146
147IpmbResponse::IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun,
148 uint8_t rsSA, uint8_t seq, uint8_t rsLun,
149 uint8_t cmd, uint8_t completionCode,
150 std::vector<uint8_t> &inputData) :
151 address(address),
152 netFn(netFn), rqLun(rqLun), rsSA(rsSA), seq(seq), rsLun(rsLun), cmd(cmd),
153 completionCode(completionCode)
154{
155 data.reserve(ipmbMaxDataSize);
156
157 if (inputData.size() > 0)
158 {
159 data = std::move(inputData);
160 }
161}
162
163void IpmbResponse::ipmbToi2cConstruct(uint8_t *buffer, size_t *bufferLength)
164{
165 ipmbHeader *ipmbBuffer = (ipmbHeader *)buffer;
166
167 ipmbBuffer->Header.Resp.address = address;
168 ipmbBuffer->Header.Resp.rqNetFnLUN = ipmbNetFnLunSet(netFn, rqLun);
169 ipmbBuffer->Header.Resp.rsSA = rsSA;
170 ipmbBuffer->Header.Resp.rsSeqLUN = ipmbSeqLunSet(seq, rsLun);
171 ipmbBuffer->Header.Resp.cmd = cmd;
172 ipmbBuffer->Header.Resp.completionCode = completionCode;
173
174 ipmbBuffer->Header.Resp.checksum1 = ipmbChecksumCompute(
175 buffer, ipmbConnectionHeaderLength - ipmbChecksumSize);
176
177 if (data.size() > 0)
178 {
179 std::copy(
180 data.begin(), data.end(),
181 &buffer[ipmbConnectionHeaderLength + ipmbResponseDataHeaderLength]);
182 }
183
184 *bufferLength = data.size() + ipmbResponseDataHeaderLength +
185 ipmbConnectionHeaderLength + ipmbChecksumSize;
186
187 buffer[*bufferLength - ipmbChecksumSize] =
188 ipmbChecksumCompute(&buffer[ipmbChecksum2StartOffset],
189 (ipmbResponseDataHeaderLength + data.size()));
190}
191
192void IpmbRequest::prepareRequest(sdbusplus::message::message &mesg)
193{
194 mesg.append(ipmbMeChannelNum, netFn, rqLun, cmd, data);
195}
196
Richard Marian Thomaiyare646a252019-11-20 22:54:03 +0530197static constexpr unsigned int makeCmdKey(unsigned int netFn, unsigned int cmd)
198{
199 return (netFn << 8) | cmd;
200}
201
202static constexpr bool isMeCmdAllowed(uint8_t netFn, uint8_t cmd)
203{
204 constexpr uint8_t netFnMeOEM = 0x2E;
Yong Liedbb4082020-03-06 17:38:25 +0800205 constexpr uint8_t netFnMeOEMGeneral = 0x3E;
Richard Marian Thomaiyare646a252019-11-20 22:54:03 +0530206 constexpr uint8_t cmdMeOemSendRawPeci = 0x40;
207 constexpr uint8_t cmdMeOemAggSendRawPeci = 0x41;
208 constexpr uint8_t cmdMeOemCpuPkgConfWrite = 0x43;
209 constexpr uint8_t cmdMeOemCpuPciConfWrite = 0x45;
210 constexpr uint8_t cmdMeOemReadMemSmbus = 0x47;
211 constexpr uint8_t cmdMeOemWriteMemSmbus = 0x48;
212 constexpr uint8_t cmdMeOemSlotIpmb = 0x51;
213 constexpr uint8_t cmdMeOemSlotI2cMasterWriteRead = 0x52;
214 constexpr uint8_t cmdMeOemSendRawPmbus = 0xD9;
215 constexpr uint8_t cmdMeOemUnlockMeRegion = 0xE7;
216 constexpr uint8_t cmdMeOemAggSendRawPmbus = 0xEC;
217
218 switch (makeCmdKey(netFn, cmd))
219 {
220 // Restrict ME Master write command
221 case makeCmdKey(ipmi::netFnApp, ipmi::app::cmdMasterWriteRead):
222 // Restrict ME OEM commands
223 case makeCmdKey(netFnMeOEM, cmdMeOemSendRawPeci):
224 case makeCmdKey(netFnMeOEM, cmdMeOemAggSendRawPeci):
225 case makeCmdKey(netFnMeOEM, cmdMeOemCpuPkgConfWrite):
226 case makeCmdKey(netFnMeOEM, cmdMeOemCpuPciConfWrite):
227 case makeCmdKey(netFnMeOEM, cmdMeOemReadMemSmbus):
228 case makeCmdKey(netFnMeOEM, cmdMeOemWriteMemSmbus):
Yong Liedbb4082020-03-06 17:38:25 +0800229 case makeCmdKey(netFnMeOEMGeneral, cmdMeOemSlotIpmb):
230 case makeCmdKey(netFnMeOEMGeneral, cmdMeOemSlotI2cMasterWriteRead):
Richard Marian Thomaiyare646a252019-11-20 22:54:03 +0530231 case makeCmdKey(netFnMeOEM, cmdMeOemSendRawPmbus):
232 case makeCmdKey(netFnMeOEM, cmdMeOemUnlockMeRegion):
233 case makeCmdKey(netFnMeOEM, cmdMeOemAggSendRawPmbus):
234 return false;
235 default:
236 return true;
237 }
238}
239
Vernon Mauerya3702c12019-05-22 13:20:59 -0700240ipmi_return_codes Bridging::handleIpmbChannel(sSendMessageReq *sendMsgReq,
241 ipmi_response_t response,
242 ipmi_data_len_t dataLen)
243{
Yong Liedbb4082020-03-06 17:38:25 +0800244 ipmi::Manufacturing mtm;
245
Vernon Mauerya3702c12019-05-22 13:20:59 -0700246 if ((*dataLen < (sizeof(sSendMessageReq) + ipmbMinFrameLength)) ||
247 (*dataLen > (sizeof(sSendMessageReq) + ipmbMaxFrameLength)))
248 {
249 *dataLen = 0;
250 return IPMI_CC_REQ_DATA_LEN_INVALID;
251 }
252
253 auto sendMsgReqData = reinterpret_cast<ipmbHeader *>(sendMsgReq->data);
254
255 // TODO: check privilege lvl. Bridging to ME requires Administrator lvl
256
257 // allow bridging to ME only
258 if (sendMsgReqData->Header.Req.address != ipmbMeSlaveAddress)
259 {
260 phosphor::logging::log<phosphor::logging::level::INFO>(
261 "handleIpmbChannel, IPMB address invalid");
262 *dataLen = 0;
263 return IPMI_CC_PARM_OUT_OF_RANGE;
264 }
265
Richard Marian Thomaiyare646a252019-11-20 22:54:03 +0530266 constexpr uint8_t shiftLUN = 2;
Yong Liedbb4082020-03-06 17:38:25 +0800267 if (mtm.getMfgMode() == ipmi::SpecialMode::none)
Richard Marian Thomaiyare646a252019-11-20 22:54:03 +0530268 {
Yong Liedbb4082020-03-06 17:38:25 +0800269 if (!isMeCmdAllowed((sendMsgReqData->Header.Req.rsNetFnLUN >> shiftLUN),
270 sendMsgReqData->Header.Req.cmd))
271 {
272 return IPMI_CC_INSUFFICIENT_PRIVILEGE;
273 }
Richard Marian Thomaiyare646a252019-11-20 22:54:03 +0530274 }
275
Vernon Mauerya3702c12019-05-22 13:20:59 -0700276 // check allowed modes
277 if (sendMsgReq->modeGet() != modeNoTracking &&
278 sendMsgReq->modeGet() != modeTrackRequest)
279 {
280 phosphor::logging::log<phosphor::logging::level::INFO>(
281 "handleIpmbChannel, mode not supported");
282 *dataLen = 0;
283 return IPMI_CC_PARM_OUT_OF_RANGE;
284 }
285
286 // check if request contains valid IPMB frame
287 if (!isFrameValid(sendMsgReqData, (*dataLen - sizeof(sSendMessageReq))))
288 {
289 phosphor::logging::log<phosphor::logging::level::INFO>(
290 "handleIpmbChannel, IPMB frame invalid");
291 *dataLen = 0;
292 return IPMI_CC_PARM_OUT_OF_RANGE;
293 }
294
295 auto ipmbRequest =
296 IpmbRequest(sendMsgReqData, (*dataLen - sizeof(sSendMessageReq)));
297
298 std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
299 ipmbResponse;
300
301 // send request to IPMB
302 try
303 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700304 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700305 auto mesg =
Vernon Mauery15419dd2019-05-24 09:40:30 -0700306 dbus->new_method_call(ipmbBus, ipmbObj, ipmbIntf, "sendRequest");
Vernon Mauerya3702c12019-05-22 13:20:59 -0700307 ipmbRequest.prepareRequest(mesg);
Vernon Mauery15419dd2019-05-24 09:40:30 -0700308 auto ret = dbus->call(mesg);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700309 ret.read(ipmbResponse);
310 }
311 catch (sdbusplus::exception::SdBusError &e)
312 {
313 phosphor::logging::log<phosphor::logging::level::ERR>(
314 "handleIpmbChannel, dbus call exception");
315 *dataLen = 0;
316 return IPMI_CC_UNSPECIFIED_ERROR;
317 }
318
319 std::vector<uint8_t> dataReceived(0);
320 int status = -1;
321 uint8_t netFn = 0, lun = 0, cmd = 0, cc = 0;
322
323 std::tie(status, netFn, lun, cmd, cc, dataReceived) = ipmbResponse;
324
325 auto respReceived =
326 IpmbResponse(ipmbRequest.rqSA, netFn, lun, ipmbRequest.address,
327 ipmbRequest.seq, lun, cmd, cc, dataReceived);
328
329 // check IPMB layer status
330 if (status)
331 {
332 phosphor::logging::log<phosphor::logging::level::WARNING>(
333 "handleIpmbChannel, ipmb returned non zero status");
334 *dataLen = 0;
335 return IPMI_CC_RESPONSE_ERROR;
336 }
337
338 auto sendMsgRes = reinterpret_cast<uint8_t *>(response);
339
340 switch (sendMsgReq->modeGet())
341 {
342 case modeNoTracking:
343 if (responseQueue.size() == responseQueueMaxSize)
344 {
345 *dataLen = 0;
346 return IPMI_CC_BUSY;
347 }
348 responseQueue.insert(responseQueue.end(), std::move(respReceived));
349 *dataLen = 0;
350 return IPMI_CC_OK;
351
352 break;
353 case modeTrackRequest:
354 respReceived.ipmbToi2cConstruct(sendMsgRes, dataLen);
355 return IPMI_CC_OK;
356
357 break;
358 default:
359 phosphor::logging::log<phosphor::logging::level::INFO>(
360 "handleIpmbChannel, mode not supported");
361 *dataLen = 0;
362 return IPMI_CC_PARM_OUT_OF_RANGE;
363 }
364
365 *dataLen = 0;
366 return IPMI_CC_UNSPECIFIED_ERROR;
367}
368
369ipmi_return_codes Bridging::sendMessageHandler(ipmi_request_t request,
370 ipmi_response_t response,
371 ipmi_data_len_t dataLen)
372{
373 ipmi_return_codes retCode = IPMI_CC_OK;
374
375 if (*dataLen < sizeof(sSendMessageReq))
376 {
377 *dataLen = 0;
378 return IPMI_CC_REQ_DATA_LEN_INVALID;
379 }
380
381 auto sendMsgReq = reinterpret_cast<sSendMessageReq *>(request);
382
383 // check message fields:
384 // encryption not supported
385 if (sendMsgReq->encryptionGet() != 0)
386 {
387 phosphor::logging::log<phosphor::logging::level::INFO>(
388 "sendMessageHandler, encryption not supported");
389 *dataLen = 0;
390 return IPMI_CC_PARM_OUT_OF_RANGE;
391 }
392
393 // authentication not supported
394 if (sendMsgReq->authenticationGet() != 0)
395 {
396 phosphor::logging::log<phosphor::logging::level::INFO>(
397 "sendMessageHandler, authentication not supported");
398 *dataLen = 0;
399 return IPMI_CC_PARM_OUT_OF_RANGE;
400 }
401
402 switch (sendMsgReq->channelNumGet())
403 {
404 // we only handle ipmb for now
405 case targetChannelIpmb:
406 case targetChannelOtherLan:
407 retCode = handleIpmbChannel(sendMsgReq, response, dataLen);
408 break;
409 // fall through to default
410 case targetChannelIcmb10:
411 case targetChannelIcmb09:
412 case targetChannelLan:
413 case targetChannelSerialModem:
414 case targetChannelPciSmbus:
415 case targetChannelSmbus10:
416 case targetChannelSmbus20:
417 case targetChannelSystemInterface:
418 default:
419 phosphor::logging::log<phosphor::logging::level::INFO>(
420 "sendMessageHandler, TargetChannel invalid");
421 *dataLen = 0;
422 return IPMI_CC_PARM_OUT_OF_RANGE;
423 }
424
425 return retCode;
426}
427
428ipmi_return_codes Bridging::getMessageHandler(ipmi_request_t request,
429 ipmi_response_t response,
430 ipmi_data_len_t dataLen)
431{
432 if (*dataLen != 0)
433 {
434 *dataLen = 0;
435 return IPMI_CC_REQ_DATA_LEN_INVALID;
436 }
437
438 auto getMsgRes = reinterpret_cast<sGetMessageRes *>(response);
439 auto getMsgResData = static_cast<uint8_t *>(getMsgRes->data);
440
441 std::memset(getMsgRes, 0, sizeof(sGetMessageRes));
442
443 auto respQueueItem = responseQueue.begin();
444
445 if (respQueueItem == responseQueue.end())
446 {
447 phosphor::logging::log<phosphor::logging::level::INFO>(
448 "getMessageHandler, no data available");
449 *dataLen = 0;
450 return ipmiGetMessageCmdDataNotAvailable;
451 }
452
453 // set message fields
454 getMsgRes->privilegeLvlSet(SYSTEM_INTERFACE);
455 getMsgRes->channelNumSet(targetChannelSystemInterface);
456
457 // construct response
458 respQueueItem->ipmbToi2cConstruct(getMsgResData, dataLen);
459 responseQueue.erase(respQueueItem);
460
461 *dataLen = *dataLen + sizeof(sGetMessageRes);
462 return IPMI_CC_OK;
463}
464
Vernon Mauerya3702c12019-05-22 13:20:59 -0700465ipmi_ret_t ipmiAppSendMessage(ipmi_netfn_t netFn, ipmi_cmd_t cmd,
466 ipmi_request_t request, ipmi_response_t response,
467 ipmi_data_len_t dataLen, ipmi_context_t context)
468{
469 ipmi_ret_t retCode = IPMI_CC_OK;
470 retCode = bridging.sendMessageHandler(request, response, dataLen);
471
472 return retCode;
473}
474
475ipmi_ret_t ipmiAppGetMessage(ipmi_netfn_t netFn, ipmi_cmd_t cmd,
476 ipmi_request_t request, ipmi_response_t response,
477 ipmi_data_len_t dataLen, ipmi_context_t context)
478{
479 ipmi_ret_t retCode = IPMI_CC_OK;
480 retCode = bridging.getMessageHandler(request, response, dataLen);
481
482 return retCode;
483}
484
Yong Lic3580e92019-08-15 14:36:47 +0800485std::size_t Bridging::getResponseQueueSize()
Vernon Mauerya3702c12019-05-22 13:20:59 -0700486{
Yong Lic3580e92019-08-15 14:36:47 +0800487 return responseQueue.size();
488}
Vernon Mauerya3702c12019-05-22 13:20:59 -0700489
Yong Lic3580e92019-08-15 14:36:47 +0800490/**
491@brief This command is used to retrive present message available states.
492
493@return IPMI completion code plus Flags as response data on success.
494**/
495ipmi::RspType<std::bitset<8>> ipmiAppGetMessageFlags()
496{
497 std::bitset<8> getMsgFlagsRes;
498
jayaprakash Mutyala5ba46872019-11-20 00:02:48 +0000499 // set event message buffer bit
500 if (!eventMessageBufferFlag)
501 {
502 getMsgFlagsRes.set(getMsgFlagEventMessageBit);
503 }
504 else
505 {
506 getMsgFlagsRes.reset(getMsgFlagEventMessageBit);
507 }
Yong Lic3580e92019-08-15 14:36:47 +0800508
509 // set message fields
510 if (bridging.getResponseQueueSize() > 0)
511 {
512 getMsgFlagsRes.set(getMsgFlagReceiveMessageBit);
513 }
514 else
515 {
516 getMsgFlagsRes.reset(getMsgFlagReceiveMessageBit);
517 }
518
519 try
520 {
521 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
522 ipmi::Value variant = ipmi::getDbusProperty(
523 *dbus, wdtService, wdtObjPath, wdtInterface, wdtInterruptFlagProp);
524 if (std::get<bool>(variant))
525 {
526 getMsgFlagsRes.set(getMsgFlagWatchdogPreTimeOutBit);
527 }
528 }
529 catch (sdbusplus::exception::SdBusError &e)
530 {
531 phosphor::logging::log<phosphor::logging::level::ERR>(
532 "ipmiAppGetMessageFlags, dbus call exception");
533 return ipmi::responseUnspecifiedError();
534 }
535
536 return ipmi::responseSuccess(getMsgFlagsRes);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700537}
538
jayaprakash Mutyala405f54a2019-10-18 18:23:27 +0000539/** @brief This command is used to flush unread data from the receive
540 * message queue
541 * @param receiveMessage - clear receive message queue
542 * @param eventMsgBufFull - clear event message buffer full
543 * @param reserved2 - reserved bit
544 * @param watchdogTimeout - clear watchdog pre-timeout interrupt flag
545 * @param reserved1 - reserved bit
546 * @param oem0 - clear OEM 0 data
547 * @param oem1 - clear OEM 1 data
548 * @param oem2 - clear OEM 2 data
549
550 * @return IPMI completion code on success
551 */
552ipmi::RspType<> ipmiAppClearMessageFlags(bool receiveMessage,
553 bool eventMsgBufFull, bool reserved2,
554 bool watchdogTimeout, bool reserved1,
555 bool oem0, bool oem1, bool oem2)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700556{
jayaprakash Mutyala405f54a2019-10-18 18:23:27 +0000557 if (reserved1 || reserved2)
558 {
559 return ipmi::responseInvalidFieldRequest();
560 }
Vernon Mauerya3702c12019-05-22 13:20:59 -0700561
jayaprakash Mutyala405f54a2019-10-18 18:23:27 +0000562 if (receiveMessage)
563 {
564 bridging.clearResponseQueue();
565 }
jayaprakash Mutyala5ba46872019-11-20 00:02:48 +0000566
567 if (eventMessageBufferFlag != true && eventMsgBufFull == true)
568 {
569 eventMessageBufferFlag = true;
570 }
571
jayaprakash Mutyala43539cb2019-11-25 12:37:27 +0000572 try
573 {
574 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
575 ipmi::setDbusProperty(*dbus, wdtService, wdtObjPath, wdtInterface,
576 wdtInterruptFlagProp, false);
577 }
578 catch (const sdbusplus::exception::SdBusError &e)
579 {
580 phosphor::logging::log<phosphor::logging::level::ERR>(
581 "ipmiAppClearMessageFlags: can't Clear/Set "
582 "PreTimeoutInterruptOccurFlag");
583 return ipmi::responseUnspecifiedError();
584 }
585
jayaprakash Mutyala405f54a2019-10-18 18:23:27 +0000586 return ipmi::responseSuccess();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700587}
588
jayaprakash Mutyala5ba46872019-11-20 00:02:48 +0000589using systemEventType = std::tuple<
590 uint16_t, // Generator ID
591 uint32_t, // Timestamp
592 uint8_t, // Sensor Type
593 uint8_t, // EvM Rev
594 uint8_t, // Sensor Number
595 uint7_t, // Event Type
596 bool, // Event Direction
597 std::array<uint8_t, intel_oem::ipmi::sel::systemEventSize>>; // Event Data
598using oemTsEventType = std::tuple<
599 uint32_t, // Timestamp
600 std::array<uint8_t, intel_oem::ipmi::sel::oemTsEventSize>>; // Event Data
601using oemEventType =
602 std::array<uint8_t, intel_oem::ipmi::sel::oemEventSize>; // Event Data
603
604/** @brief implements of Read event message buffer command
605 *
606 * @returns IPMI completion code plus response data
607 * - recordID - SEL Record ID
608 * - recordType - Record Type
609 * - generatorID - Generator ID
610 * - timeStamp - Timestamp
611 * - sensorType - Sensor Type
612 * - eventMsgFormatRev - Event Message format version
613 * - sensorNumber - Sensor Number
614 * - eventType - Event Type
615 * - eventDir - Event Direction
616 * - eventData - Event Data field
617 */
618ipmi::RspType<uint16_t, // Record ID
619 uint8_t, // Record Type
620 std::variant<systemEventType, oemTsEventType,
621 oemEventType>> // Record Content
622 ipmiAppReadEventMessageBuffer()
623{
624 uint16_t recordId =
625 static_cast<uint16_t>(0x5555); // recordId: 0x55 << 8 | 0x55
626 uint16_t generatorId =
627 static_cast<uint16_t>(0xA741); // generatorId: 0xA7 << 8 | 0x41
628 constexpr uint8_t recordType = 0xC0;
629 constexpr uint8_t eventMsgFormatRev = 0x3A;
630 constexpr uint8_t sensorNumber = 0xFF;
631
632 // TODO need to be implemented.
633 std::array<uint8_t, intel_oem::ipmi::sel::systemEventSize> eventData{};
634 // All '0xFF' since unused.
635 eventData.fill(0xFF);
636
637 // Set the event message buffer flag
638 eventMessageBufferFlag = true;
639
640 return ipmi::responseSuccess(
641 recordId, recordType,
642 systemEventType{generatorId, 0, 0, eventMsgFormatRev, sensorNumber,
643 static_cast<uint7_t>(0), false, eventData});
644}
645
Vernon Mauerya3702c12019-05-22 13:20:59 -0700646static void register_bridging_functions() __attribute__((constructor));
647static void register_bridging_functions()
648{
jayaprakash Mutyala405f54a2019-10-18 18:23:27 +0000649 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnApp,
650 ipmi::app::cmdClearMessageFlags,
651 ipmi::Privilege::User, ipmiAppClearMessageFlags);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700652
Yong Lic3580e92019-08-15 14:36:47 +0800653 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnApp,
654 ipmi::app::cmdGetMessageFlags, ipmi::Privilege::User,
655 ipmiAppGetMessageFlags);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700656
657 ipmi_register_callback(NETFUN_APP,
658 Bridging::IpmiAppBridgingCmds::ipmiCmdGetMessage,
659 NULL, ipmiAppGetMessage, PRIVILEGE_USER);
660
661 ipmi_register_callback(NETFUN_APP,
662 Bridging::IpmiAppBridgingCmds::ipmiCmdSendMessage,
663 NULL, ipmiAppSendMessage, PRIVILEGE_USER);
664
jayaprakash Mutyala5ba46872019-11-20 00:02:48 +0000665 ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnApp,
666 ipmi::app::cmdReadEventMessageBuffer,
667 ipmi::Privilege::User, ipmiAppReadEventMessageBuffer);
668
Vernon Mauerya3702c12019-05-22 13:20:59 -0700669 return;
670}