bridgingcommands.cpp (e95b0e5512f55e7c0b764462e7c815187589a598) bridgingcommands.cpp (fcd2d3a943c4fb518d399d8a0addd1cc661e5628)
1/*
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
1/*
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
17#include <bitset>
18#include <bridgingcommands.hpp>
17#include <bridgingcommands.hpp>
19#include <cstring>
20#include <ipmid/api.hpp>
21#include <ipmid/utils.hpp>
22#include <manufacturingcommands.hpp>
23#include <phosphor-logging/log.hpp>
24#include <sdbusplus/bus.hpp>
25#include <sdbusplus/bus/match.hpp>
26#include <sdbusplus/message.hpp>
27#include <storagecommands.hpp>
18#include <ipmid/api.hpp>
19#include <ipmid/utils.hpp>
20#include <manufacturingcommands.hpp>
21#include <phosphor-logging/log.hpp>
22#include <sdbusplus/bus.hpp>
23#include <sdbusplus/bus/match.hpp>
24#include <sdbusplus/message.hpp>
25#include <storagecommands.hpp>
26
27#include <bitset>
28#include <cstring>
28#include <vector>
29
29#include <vector>
30
30static constexpr const char *wdtService = "xyz.openbmc_project.Watchdog";
31static constexpr const char *wdtInterface =
31static constexpr const char* wdtService = "xyz.openbmc_project.Watchdog";
32static constexpr const char* wdtInterface =
32 "xyz.openbmc_project.State.Watchdog";
33 "xyz.openbmc_project.State.Watchdog";
33static constexpr const char *wdtObjPath = "/xyz/openbmc_project/watchdog/host0";
34static constexpr const char *wdtInterruptFlagProp =
34static constexpr const char* wdtObjPath = "/xyz/openbmc_project/watchdog/host0";
35static constexpr const char* wdtInterruptFlagProp =
35 "PreTimeoutInterruptOccurFlag";
36
36 "PreTimeoutInterruptOccurFlag";
37
37static 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";
38static constexpr const char* ipmbBus = "xyz.openbmc_project.Ipmi.Channel.Ipmb";
39static constexpr const char* ipmbObj = "/xyz/openbmc_project/Ipmi/Channel/Ipmb";
40static constexpr const char* ipmbIntf = "org.openbmc.Ipmb";
40
41static Bridging bridging;
42static bool eventMessageBufferFlag = false;
43
44void Bridging::clearResponseQueue()
45{
46 responseQueue.clear();
47}
48
49/**
50 * @brief utils for checksum
51 */
41
42static Bridging bridging;
43static bool eventMessageBufferFlag = false;
44
45void Bridging::clearResponseQueue()
46{
47 responseQueue.clear();
48}
49
50/**
51 * @brief utils for checksum
52 */
52static bool ipmbChecksumValidate(const uint8_t *data, uint8_t length)
53static bool ipmbChecksumValidate(const uint8_t* data, uint8_t length)
53{
54 if (data == nullptr)
55 {
56 return false;
57 }
58
59 uint8_t checksum = 0;
60

--- 5 unchanged lines hidden (view full) ---

66 if (0 == checksum)
67 {
68 return true;
69 }
70
71 return false;
72}
73
54{
55 if (data == nullptr)
56 {
57 return false;
58 }
59
60 uint8_t checksum = 0;
61

--- 5 unchanged lines hidden (view full) ---

67 if (0 == checksum)
68 {
69 return true;
70 }
71
72 return false;
73}
74
74static uint8_t ipmbChecksumCompute(uint8_t *data, uint8_t length)
75static 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
76{
77 if (data == nullptr)
78 {
79 return 0;
80 }
81
82 uint8_t checksum = 0;
83
84 for (uint8_t idx = 0; idx < length; idx++)
85 {
86 checksum += data[idx];
87 }
88
89 checksum = (~checksum) + 1;
90 return checksum;
91}
92
93static inline bool
93 ipmbConnectionHeaderChecksumValidate(const ipmbHeader *ipmbHeader)
94 ipmbConnectionHeaderChecksumValidate(const ipmbHeader* ipmbHeader)
94{
95{
95 return ipmbChecksumValidate(reinterpret_cast<const uint8_t *>(ipmbHeader),
96 return ipmbChecksumValidate(reinterpret_cast<const uint8_t*>(ipmbHeader),
96 ipmbConnectionHeaderLength);
97}
98
97 ipmbConnectionHeaderLength);
98}
99
99static inline bool ipmbDataChecksumValidate(const ipmbHeader *ipmbHeader,
100static inline bool ipmbDataChecksumValidate(const ipmbHeader* ipmbHeader,
100 uint8_t length)
101{
101 uint8_t length)
102{
102 return ipmbChecksumValidate((reinterpret_cast<const uint8_t *>(ipmbHeader) +
103 return ipmbChecksumValidate((reinterpret_cast<const uint8_t*>(ipmbHeader) +
103 ipmbConnectionHeaderLength),
104 (length - ipmbConnectionHeaderLength));
105}
106
104 ipmbConnectionHeaderLength),
105 (length - ipmbConnectionHeaderLength));
106}
107
107static bool isFrameValid(const ipmbHeader *frame, uint8_t length)
108static bool isFrameValid(const ipmbHeader* frame, uint8_t length)
108{
109 if ((length < ipmbMinFrameLength) || (length > ipmbMaxFrameLength))
110 {
111 return false;
112 }
113
114 if (false == ipmbConnectionHeaderChecksumValidate(frame))
115 {
116 return false;
117 }
118
119 if (false == ipmbDataChecksumValidate(frame, length))
120 {
121 return false;
122 }
123
124 return true;
125}
126
109{
110 if ((length < ipmbMinFrameLength) || (length > ipmbMaxFrameLength))
111 {
112 return false;
113 }
114
115 if (false == ipmbConnectionHeaderChecksumValidate(frame))
116 {
117 return false;
118 }
119
120 if (false == ipmbDataChecksumValidate(frame, length))
121 {
122 return false;
123 }
124
125 return true;
126}
127
127IpmbRequest::IpmbRequest(const ipmbHeader *ipmbBuffer, size_t bufferLength)
128IpmbRequest::IpmbRequest(const ipmbHeader* ipmbBuffer, size_t bufferLength)
128{
129 address = ipmbBuffer->Header.Req.address;
130 netFn = ipmbNetFnGet(ipmbBuffer->Header.Req.rsNetFnLUN);
131 rsLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Req.rsNetFnLUN);
132 rqSA = ipmbBuffer->Header.Req.rqSA;
133 seq = ipmbSeqGet(ipmbBuffer->Header.Req.rqSeqLUN);
134 rqLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Req.rqSeqLUN);
135 cmd = ipmbBuffer->Header.Req.cmd;

--- 7 unchanged lines hidden (view full) ---

143 data.insert(data.end(), ipmbBuffer->Header.Req.data,
144 &ipmbBuffer->Header.Req.data[dataLength]);
145 }
146}
147
148IpmbResponse::IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun,
149 uint8_t rsSA, uint8_t seq, uint8_t rsLun,
150 uint8_t cmd, uint8_t completionCode,
129{
130 address = ipmbBuffer->Header.Req.address;
131 netFn = ipmbNetFnGet(ipmbBuffer->Header.Req.rsNetFnLUN);
132 rsLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Req.rsNetFnLUN);
133 rqSA = ipmbBuffer->Header.Req.rqSA;
134 seq = ipmbSeqGet(ipmbBuffer->Header.Req.rqSeqLUN);
135 rqLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Req.rqSeqLUN);
136 cmd = ipmbBuffer->Header.Req.cmd;

--- 7 unchanged lines hidden (view full) ---

144 data.insert(data.end(), ipmbBuffer->Header.Req.data,
145 &ipmbBuffer->Header.Req.data[dataLength]);
146 }
147}
148
149IpmbResponse::IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun,
150 uint8_t rsSA, uint8_t seq, uint8_t rsLun,
151 uint8_t cmd, uint8_t completionCode,
151 std::vector<uint8_t> &inputData) :
152 std::vector<uint8_t>& inputData) :
152 address(address),
153 netFn(netFn), rqLun(rqLun), rsSA(rsSA), seq(seq), rsLun(rsLun), cmd(cmd),
154 completionCode(completionCode)
155{
156 data.reserve(ipmbMaxDataSize);
157
158 if (inputData.size() > 0)
159 {
160 data = std::move(inputData);
161 }
162}
163
153 address(address),
154 netFn(netFn), rqLun(rqLun), rsSA(rsSA), seq(seq), rsLun(rsLun), cmd(cmd),
155 completionCode(completionCode)
156{
157 data.reserve(ipmbMaxDataSize);
158
159 if (inputData.size() > 0)
160 {
161 data = std::move(inputData);
162 }
163}
164
164void IpmbResponse::ipmbToi2cConstruct(uint8_t *buffer, size_t *bufferLength)
165void IpmbResponse::ipmbToi2cConstruct(uint8_t* buffer, size_t* bufferLength)
165{
166{
166 ipmbHeader *ipmbBuffer = (ipmbHeader *)buffer;
167 ipmbHeader* ipmbBuffer = (ipmbHeader*)buffer;
167
168 ipmbBuffer->Header.Resp.address = address;
169 ipmbBuffer->Header.Resp.rqNetFnLUN = ipmbNetFnLunSet(netFn, rqLun);
170 ipmbBuffer->Header.Resp.rsSA = rsSA;
171 ipmbBuffer->Header.Resp.rsSeqLUN = ipmbSeqLunSet(seq, rsLun);
172 ipmbBuffer->Header.Resp.cmd = cmd;
173 ipmbBuffer->Header.Resp.completionCode = completionCode;
174

--- 10 unchanged lines hidden (view full) ---

185 *bufferLength = data.size() + ipmbResponseDataHeaderLength +
186 ipmbConnectionHeaderLength + ipmbChecksumSize;
187
188 buffer[*bufferLength - ipmbChecksumSize] =
189 ipmbChecksumCompute(&buffer[ipmbChecksum2StartOffset],
190 (ipmbResponseDataHeaderLength + data.size()));
191}
192
168
169 ipmbBuffer->Header.Resp.address = address;
170 ipmbBuffer->Header.Resp.rqNetFnLUN = ipmbNetFnLunSet(netFn, rqLun);
171 ipmbBuffer->Header.Resp.rsSA = rsSA;
172 ipmbBuffer->Header.Resp.rsSeqLUN = ipmbSeqLunSet(seq, rsLun);
173 ipmbBuffer->Header.Resp.cmd = cmd;
174 ipmbBuffer->Header.Resp.completionCode = completionCode;
175

--- 10 unchanged lines hidden (view full) ---

186 *bufferLength = data.size() + ipmbResponseDataHeaderLength +
187 ipmbConnectionHeaderLength + ipmbChecksumSize;
188
189 buffer[*bufferLength - ipmbChecksumSize] =
190 ipmbChecksumCompute(&buffer[ipmbChecksum2StartOffset],
191 (ipmbResponseDataHeaderLength + data.size()));
192}
193
193void IpmbRequest::prepareRequest(sdbusplus::message::message &mesg)
194void IpmbRequest::prepareRequest(sdbusplus::message::message& mesg)
194{
195 mesg.append(ipmbMeChannelNum, netFn, rqLun, cmd, data);
196}
197
198static constexpr unsigned int makeCmdKey(unsigned int netFn, unsigned int cmd)
199{
200 return (netFn << 8) | cmd;
201}

--- 33 unchanged lines hidden (view full) ---

235 return false;
236 default:
237 return true;
238 }
239}
240
241ipmi::Cc Bridging::handleIpmbChannel(ipmi::Context::ptr ctx,
242 const uint8_t tracking,
195{
196 mesg.append(ipmbMeChannelNum, netFn, rqLun, cmd, data);
197}
198
199static constexpr unsigned int makeCmdKey(unsigned int netFn, unsigned int cmd)
200{
201 return (netFn << 8) | cmd;
202}

--- 33 unchanged lines hidden (view full) ---

236 return false;
237 default:
238 return true;
239 }
240}
241
242ipmi::Cc Bridging::handleIpmbChannel(ipmi::Context::ptr ctx,
243 const uint8_t tracking,
243 const std::vector<uint8_t> &msgData,
244 std::vector<uint8_t> &rspData)
244 const std::vector<uint8_t>& msgData,
245 std::vector<uint8_t>& rspData)
245{
246 ipmi::Manufacturing mtm;
247
248 size_t msgLen = msgData.size();
249 if ((msgLen < ipmbMinFrameLength) || (msgLen > ipmbMaxFrameLength))
250 {
251 phosphor::logging::log<phosphor::logging::level::INFO>(
252 "handleIpmbChannel, IPMB data length is invalid");
253 return ipmi::ccReqDataLenInvalid;
254 }
255
256 // Bridging to ME requires Administrator lvl
257 if ((ctx->priv) != ipmi::Privilege::Admin)
258 {
259 return ipmi::ccInsufficientPrivilege;
260 }
261
246{
247 ipmi::Manufacturing mtm;
248
249 size_t msgLen = msgData.size();
250 if ((msgLen < ipmbMinFrameLength) || (msgLen > ipmbMaxFrameLength))
251 {
252 phosphor::logging::log<phosphor::logging::level::INFO>(
253 "handleIpmbChannel, IPMB data length is invalid");
254 return ipmi::ccReqDataLenInvalid;
255 }
256
257 // Bridging to ME requires Administrator lvl
258 if ((ctx->priv) != ipmi::Privilege::Admin)
259 {
260 return ipmi::ccInsufficientPrivilege;
261 }
262
262 auto sendMsgReqData = reinterpret_cast<const ipmbHeader *>(msgData.data());
263 auto sendMsgReqData = reinterpret_cast<const ipmbHeader*>(msgData.data());
263
264 // allow bridging to ME only
265 if (sendMsgReqData->Header.Req.address != ipmbMeSlaveAddress)
266 {
267 phosphor::logging::log<phosphor::logging::level::INFO>(
268 "handleIpmbChannel, IPMB address invalid");
269 return ipmi::ccParmOutOfRange;
270 }

--- 118 unchanged lines hidden (view full) ---

389 * @return IPMI completion code plus response data on success.
390 * - rspData - response data
391 **/
392ipmi::RspType<std::vector<uint8_t> // responseData
393 >
394 ipmiAppSendMessage(ipmi::Context::ptr ctx, const uint4_t channelNumber,
395 const bool authenticationEnabled,
396 const bool encryptionEnabled, const uint2_t tracking,
264
265 // allow bridging to ME only
266 if (sendMsgReqData->Header.Req.address != ipmbMeSlaveAddress)
267 {
268 phosphor::logging::log<phosphor::logging::level::INFO>(
269 "handleIpmbChannel, IPMB address invalid");
270 return ipmi::ccParmOutOfRange;
271 }

--- 118 unchanged lines hidden (view full) ---

390 * @return IPMI completion code plus response data on success.
391 * - rspData - response data
392 **/
393ipmi::RspType<std::vector<uint8_t> // responseData
394 >
395 ipmiAppSendMessage(ipmi::Context::ptr ctx, const uint4_t channelNumber,
396 const bool authenticationEnabled,
397 const bool encryptionEnabled, const uint2_t tracking,
397 ipmi::message::Payload &msg)
398 ipmi::message::Payload& msg)
398{
399 // check message fields:
400 // encryption not supported
401 if (encryptionEnabled)
402 {
403 phosphor::logging::log<phosphor::logging::level::INFO>(
404 "ipmiAppSendMessage, encryption not supported");
405 return ipmi::responseParmOutOfRange();

--- 135 unchanged lines hidden (view full) ---

541 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
542 ipmi::Value variant = ipmi::getDbusProperty(
543 *dbus, wdtService, wdtObjPath, wdtInterface, wdtInterruptFlagProp);
544 if (std::get<bool>(variant))
545 {
546 getMsgFlagsRes.set(getMsgFlagWatchdogPreTimeOutBit);
547 }
548 }
399{
400 // check message fields:
401 // encryption not supported
402 if (encryptionEnabled)
403 {
404 phosphor::logging::log<phosphor::logging::level::INFO>(
405 "ipmiAppSendMessage, encryption not supported");
406 return ipmi::responseParmOutOfRange();

--- 135 unchanged lines hidden (view full) ---

542 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
543 ipmi::Value variant = ipmi::getDbusProperty(
544 *dbus, wdtService, wdtObjPath, wdtInterface, wdtInterruptFlagProp);
545 if (std::get<bool>(variant))
546 {
547 getMsgFlagsRes.set(getMsgFlagWatchdogPreTimeOutBit);
548 }
549 }
549 catch (sdbusplus::exception::SdBusError &e)
550 catch (sdbusplus::exception::SdBusError& e)
550 {
551 phosphor::logging::log<phosphor::logging::level::ERR>(
552 "ipmiAppGetMessageFlags, dbus call exception");
553 return ipmi::responseUnspecifiedError();
554 }
555
556 return ipmi::responseSuccess(getMsgFlagsRes);
557}

--- 32 unchanged lines hidden (view full) ---

590 }
591
592 try
593 {
594 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
595 ipmi::setDbusProperty(*dbus, wdtService, wdtObjPath, wdtInterface,
596 wdtInterruptFlagProp, false);
597 }
551 {
552 phosphor::logging::log<phosphor::logging::level::ERR>(
553 "ipmiAppGetMessageFlags, dbus call exception");
554 return ipmi::responseUnspecifiedError();
555 }
556
557 return ipmi::responseSuccess(getMsgFlagsRes);
558}

--- 32 unchanged lines hidden (view full) ---

591 }
592
593 try
594 {
595 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
596 ipmi::setDbusProperty(*dbus, wdtService, wdtObjPath, wdtInterface,
597 wdtInterruptFlagProp, false);
598 }
598 catch (const sdbusplus::exception::SdBusError &e)
599 catch (const sdbusplus::exception::SdBusError& e)
599 {
600 phosphor::logging::log<phosphor::logging::level::ERR>(
601 "ipmiAppClearMessageFlags: can't Clear/Set "
602 "PreTimeoutInterruptOccurFlag");
603 return ipmi::responseUnspecifiedError();
604 }
605
606 return ipmi::responseSuccess();

--- 84 unchanged lines hidden ---
600 {
601 phosphor::logging::log<phosphor::logging::level::ERR>(
602 "ipmiAppClearMessageFlags: can't Clear/Set "
603 "PreTimeoutInterruptOccurFlag");
604 return ipmi::responseUnspecifiedError();
605 }
606
607 return ipmi::responseSuccess();

--- 84 unchanged lines hidden ---