blob: 26864b8f9b8204ad03a8fe5113d2e59b5a24403c [file] [log] [blame]
Dawid Fryckia642a942018-06-12 10:44:23 -07001/* Copyright 2018 Intel
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "ipmbbridged.hpp"
17
18#include "ipmbdefines.hpp"
19#include "ipmbutils.hpp"
20
Qiang XU8edcf1a2019-06-14 22:18:15 +080021#include <boost/algorithm/string/replace.hpp>
Ed Tanous1486b8a2023-02-28 13:28:59 -080022#include <boost/asio/io_context.hpp>
Ed Tanous09027c02020-08-31 17:28:36 -070023#include <boost/asio/write.hpp>
Qiang XU8edcf1a2019-06-14 22:18:15 +080024#include <filesystem>
Amithash Prasad314862d2019-03-26 11:14:03 -070025#include <fstream>
26#include <nlohmann/json.hpp>
Dawid Fryckia642a942018-06-12 10:44:23 -070027#include <phosphor-logging/log.hpp>
28#include <tuple>
Amithash Prasad314862d2019-03-26 11:14:03 -070029#include <unordered_map>
Dawid Fryckia642a942018-06-12 10:44:23 -070030
Dawid Fryckia642a942018-06-12 10:44:23 -070031/**
32 * @brief Dbus
33 */
34static constexpr const char *ipmbBus = "xyz.openbmc_project.Ipmi.Channel.Ipmb";
35static constexpr const char *ipmbObj = "/xyz/openbmc_project/Ipmi/Channel/Ipmb";
Dawid Fryckia642a942018-06-12 10:44:23 -070036static constexpr const char *ipmbDbusIntf = "org.openbmc.Ipmb";
37
Ed Tanous1486b8a2023-02-28 13:28:59 -080038boost::asio::io_context io;
Dawid Fryckia642a942018-06-12 10:44:23 -070039auto conn = std::make_shared<sdbusplus::asio::connection>(io);
40
Dawid Fryckia642a942018-06-12 10:44:23 -070041static std::list<IpmbChannel> ipmbChannels;
Amithash Prasad314862d2019-03-26 11:14:03 -070042static const std::unordered_map<std::string, ipmbChannelType>
43 ipmbChannelTypeMap = {{"me", ipmbChannelType::me},
44 {"ipmb", ipmbChannelType::ipmb}};
Dawid Fryckia642a942018-06-12 10:44:23 -070045
46/**
47 * @brief Ipmb request class methods
48 */
49IpmbRequest::IpmbRequest()
50{
51 data.reserve(ipmbMaxDataSize);
52}
53
54IpmbRequest::IpmbRequest(uint8_t address, uint8_t netFn, uint8_t rsLun,
55 uint8_t rqSA, uint8_t seq, uint8_t rqLun, uint8_t cmd,
Dawid Frycki8188d762019-04-01 18:03:48 -070056 const std::vector<uint8_t> &inputData) :
Dawid Fryckia642a942018-06-12 10:44:23 -070057 address(address),
58 netFn(netFn), rsLun(rsLun), rqSA(rqSA), seq(seq), rqLun(rqLun), cmd(cmd),
59 timer(io)
60{
61 data.reserve(ipmbMaxDataSize);
62 state = ipmbRequestState::invalid;
63
64 if (inputData.size() > 0)
65 {
66 data = std::move(inputData);
67 }
68}
69
Dawid Fryckia642a942018-06-12 10:44:23 -070070void IpmbRequest::i2cToIpmbConstruct(IPMB_HEADER *ipmbBuffer,
71 size_t bufferLength)
72{
73 // constructing ipmb request from i2c buffer
74 netFn = ipmbNetFnGet(ipmbBuffer->Header.Req.rsNetFnLUN);
75 rsLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Req.rsNetFnLUN);
76 rqSA = ipmbBuffer->Header.Req.rqSA;
77 seq = ipmbSeqGet(ipmbBuffer->Header.Req.rqSeqLUN);
78 rqLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Req.rqSeqLUN);
79 cmd = ipmbBuffer->Header.Req.cmd;
80
81 size_t dataLength =
82 bufferLength - (ipmbConnectionHeaderLength +
83 ipmbRequestDataHeaderLength + ipmbChecksumSize);
84
85 if (dataLength > 0)
86 {
87 data.insert(data.end(), ipmbBuffer->Header.Req.data,
88 &ipmbBuffer->Header.Req.data[dataLength]);
89 }
90}
91
92int IpmbRequest::ipmbToi2cConstruct(std::vector<uint8_t> &buffer)
93{
Vijay Khemka37a7eac2019-12-06 13:52:28 -080094 /* Add one byte for length byte as per required by driver */
95 size_t bufferLength = 1 + data.size() + ipmbRequestDataHeaderLength +
Dawid Fryckia642a942018-06-12 10:44:23 -070096 ipmbConnectionHeaderLength + ipmbChecksumSize;
97
98 if (bufferLength > ipmbMaxFrameLength)
99 {
100 return -1;
101 }
102
103 buffer.resize(bufferLength);
104 static_assert(ipmbMaxFrameLength >= sizeof(IPMB_HEADER));
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800105 IPMB_PKT *ipmbPkt = reinterpret_cast<IPMB_PKT *>(buffer.data());
106 ipmbPkt->len = bufferLength - 1;
107 IPMB_HEADER *ipmbBuffer = &(ipmbPkt->hdr);
Dawid Fryckia642a942018-06-12 10:44:23 -0700108
109 // constructing buffer from ipmb request
110 ipmbBuffer->Header.Req.address = address;
111 ipmbBuffer->Header.Req.rsNetFnLUN = ipmbNetFnLunSet(netFn, rsLun);
112 ipmbBuffer->Header.Req.rqSA = rqSA;
113 ipmbBuffer->Header.Req.rqSeqLUN = ipmbSeqLunSet(seq, rqLun);
114 ipmbBuffer->Header.Req.cmd = cmd;
115
Qiang XUbbfd00a2019-06-27 21:10:06 +0800116 ipmbBuffer->Header.Req.checksum1 = ipmbChecksumCompute(
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800117 (uint8_t *)ipmbBuffer, ipmbConnectionHeaderLength - ipmbChecksumSize);
Dawid Fryckia642a942018-06-12 10:44:23 -0700118
119 if (data.size() > 0)
120 {
121 std::copy(data.begin(), data.end(), ipmbBuffer->Header.Req.data);
122 }
123
124 buffer[bufferLength - ipmbChecksumSize] =
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800125 ipmbChecksumCompute((uint8_t *)ipmbBuffer + ipmbChecksum2StartOffset,
Dawid Fryckia642a942018-06-12 10:44:23 -0700126 (ipmbRequestDataHeaderLength + data.size()));
127
128 return 0;
129}
130
131std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
132 IpmbRequest::returnMatchedResponse()
133{
134 return std::make_tuple(
135 static_cast<int>(ipmbResponseStatus::success), matchedResponse->netFn,
136 matchedResponse->rsLun, matchedResponse->cmd,
137 matchedResponse->completionCode, matchedResponse->data);
138}
139
140static std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
141 returnStatus(ipmbResponseStatus status)
142{
143 // we only want to send status here, other fields are not relevant
144 return std::make_tuple(static_cast<int>(status), 0, 0, 0, 0,
145 std::vector<uint8_t>(0));
146}
147
Dawid Fryckia642a942018-06-12 10:44:23 -0700148/**
149 * @brief Ipmb response class methods
150 */
151IpmbResponse::IpmbResponse()
152{
153 data.reserve(ipmbMaxDataSize);
154}
155
156IpmbResponse::IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun,
157 uint8_t rsSA, uint8_t seq, uint8_t rsLun,
158 uint8_t cmd, uint8_t completionCode,
Dawid Frycki8188d762019-04-01 18:03:48 -0700159 const std::vector<uint8_t> &inputData) :
Dawid Fryckia642a942018-06-12 10:44:23 -0700160 address(address),
161 netFn(netFn), rqLun(rqLun), rsSA(rsSA), seq(seq), rsLun(rsLun), cmd(cmd),
162 completionCode(completionCode)
163{
164 data.reserve(ipmbMaxDataSize);
165
166 if (inputData.size() > 0)
167 {
168 data = std::move(inputData);
169 }
170}
171
172void IpmbResponse::i2cToIpmbConstruct(IPMB_HEADER *ipmbBuffer,
173 size_t bufferLength)
174{
175 netFn = ipmbNetFnGet(ipmbBuffer->Header.Resp.rqNetFnLUN);
176 rqLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Resp.rqNetFnLUN);
177 rsSA = ipmbBuffer->Header.Resp.rsSA;
178 seq = ipmbSeqGet(ipmbBuffer->Header.Resp.rsSeqLUN);
179 rsLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Resp.rsSeqLUN);
180 cmd = ipmbBuffer->Header.Resp.cmd;
181 completionCode = ipmbBuffer->Header.Resp.completionCode;
182
183 size_t dataLength =
184 bufferLength - (ipmbConnectionHeaderLength +
185 ipmbResponseDataHeaderLength + ipmbChecksumSize);
186
187 if (dataLength > 0)
188 {
189 data.insert(data.end(), ipmbBuffer->Header.Resp.data,
190 &ipmbBuffer->Header.Resp.data[dataLength]);
191 }
192}
193
Dawid Frycki8188d762019-04-01 18:03:48 -0700194std::shared_ptr<std::vector<uint8_t>> IpmbResponse::ipmbToi2cConstruct()
Dawid Fryckia642a942018-06-12 10:44:23 -0700195{
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800196 /* Add one byte for length byte as per required by driver */
197 size_t bufferLength = 1 + data.size() + ipmbResponseDataHeaderLength +
Dawid Fryckia642a942018-06-12 10:44:23 -0700198 ipmbConnectionHeaderLength + ipmbChecksumSize;
199
200 if (bufferLength > ipmbMaxFrameLength)
201 {
Dawid Frycki8188d762019-04-01 18:03:48 -0700202 return nullptr;
Dawid Fryckia642a942018-06-12 10:44:23 -0700203 }
204
Dawid Frycki8188d762019-04-01 18:03:48 -0700205 std::shared_ptr<std::vector<uint8_t>> buffer =
206 std::make_shared<std::vector<uint8_t>>(bufferLength);
207
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800208 IPMB_PKT *ipmbPkt = reinterpret_cast<IPMB_PKT *>(buffer->data());
209 ipmbPkt->len = bufferLength - 1;
210 IPMB_HEADER *ipmbBuffer = &(ipmbPkt->hdr);
Dawid Fryckia642a942018-06-12 10:44:23 -0700211
212 ipmbBuffer->Header.Resp.address = address;
213 ipmbBuffer->Header.Resp.rqNetFnLUN = ipmbNetFnLunSet(netFn, rqLun);
214 ipmbBuffer->Header.Resp.rsSA = rsSA;
215 ipmbBuffer->Header.Resp.rsSeqLUN = ipmbSeqLunSet(seq, rsLun);
216 ipmbBuffer->Header.Resp.cmd = cmd;
217 ipmbBuffer->Header.Resp.completionCode = completionCode;
218
219 ipmbBuffer->Header.Resp.checksum1 = ipmbChecksumCompute(
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800220 (uint8_t *)ipmbBuffer, ipmbConnectionHeaderLength - ipmbChecksumSize);
Dawid Fryckia642a942018-06-12 10:44:23 -0700221
222 if (data.size() > 0)
223 {
224 std::copy(data.begin(), data.end(), ipmbBuffer->Header.Resp.data);
225 }
226
Dawid Frycki8188d762019-04-01 18:03:48 -0700227 (*buffer)[bufferLength - ipmbChecksumSize] =
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800228 ipmbChecksumCompute((uint8_t *)ipmbBuffer + ipmbChecksum2StartOffset,
Dawid Fryckia642a942018-06-12 10:44:23 -0700229 (ipmbResponseDataHeaderLength + data.size()));
230
Dawid Frycki8188d762019-04-01 18:03:48 -0700231 return buffer;
Dawid Fryckia642a942018-06-12 10:44:23 -0700232}
233
234bool IpmbCommandFilter::isBlocked(const uint8_t reqNetFn, const uint8_t cmd)
235{
236 auto blockedCmd = unhandledCommands.find({reqNetFn, cmd});
237
238 if (blockedCmd != unhandledCommands.end())
239 {
240 return true;
241 }
242
243 return false;
244}
245
246void IpmbCommandFilter::addFilter(const uint8_t reqNetFn, const uint8_t cmd)
247{
248 if (unhandledCommands.insert({reqNetFn, cmd}).second)
249 {
250 phosphor::logging::log<phosphor::logging::level::INFO>(
251 "addFilter: added command to filter",
252 phosphor::logging::entry("netFn = %d", reqNetFn),
253 phosphor::logging::entry("cmd = %d", cmd));
254 }
255}
256
257/**
258 * @brief Ipmb channel
259 */
Qiang XUbbfd00a2019-06-27 21:10:06 +0800260void IpmbChannel::ipmbSendI2cFrame(std::shared_ptr<std::vector<uint8_t>> buffer,
Dawid Fryckia642a942018-06-12 10:44:23 -0700261 size_t retriesAttempted = 0)
262{
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800263 IPMB_PKT *ipmbPkt = reinterpret_cast<IPMB_PKT *>(buffer->data());
264 uint8_t targetAddr = ipmbIsResponse(&(ipmbPkt->hdr))
265 ? ipmbPkt->hdr.Header.Resp.address
266 : ipmbPkt->hdr.Header.Req.address;
267 boost::asio::async_write(
268 i2cSlaveDescriptor, boost::asio::buffer(*buffer),
269 [this, buffer, retriesAttempted,
270 targetAddr](const boost::system::error_code &ec, size_t bytesSent) {
271 if (ec)
Dawid Fryckia642a942018-06-12 10:44:23 -0700272 {
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800273 size_t currentRetryCnt = retriesAttempted;
274
275 if (currentRetryCnt > ipmbI2cNumberOfRetries)
276 {
277 std::string msgToLog =
278 "ipmbSendI2cFrame: send to I2C failed after retries."
279 " busId=" +
280 std::to_string(ipmbBusId) +
281 ", targetAddr=" + std::to_string(targetAddr) +
282 ", error=" + ec.message();
283 phosphor::logging::log<phosphor::logging::level::ERR>(
284 msgToLog.c_str());
285 return;
286 }
287 currentRetryCnt++;
288 ipmbSendI2cFrame(buffer, currentRetryCnt);
Dawid Fryckia642a942018-06-12 10:44:23 -0700289 }
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800290 });
Dawid Fryckia642a942018-06-12 10:44:23 -0700291}
292
293/**
294 * @brief Ipmb Outstanding Requests
295 */
296void IpmbChannel::makeRequestInvalid(IpmbRequest &request)
297{
298 // change request state to invalid and remove it from outstanding requests
299 // list
300 request.state = ipmbRequestState::invalid;
301 outstandingRequests[request.seq] = nullptr;
302}
303
304void IpmbChannel::makeRequestValid(std::shared_ptr<IpmbRequest> request)
305{
306 // change request state to valid and add it to outstanding requests list
307 request->state = ipmbRequestState::valid;
308 outstandingRequests[request->seq] = request;
309}
310
311bool IpmbChannel::seqNumGet(uint8_t &seq)
312{
313 static uint8_t seqNum = 0;
314
315 for (int i = 0; i < ipmbMaxOutstandingRequestsCount; i++)
316 {
317 seqNum = ++seqNum & ipmbSeqMask;
318 if (seqNum == ipmbMaxOutstandingRequestsCount)
319 {
320 seqNum = 0;
321 }
322
323 if (outstandingRequests[seqNum] == nullptr)
324 {
325 seq = seqNum;
326 return true;
327 }
328 }
329
330 return false;
331}
332
333void IpmbChannel::responseMatch(std::unique_ptr<IpmbResponse> &response)
334{
335 std::shared_ptr<IpmbRequest> request = outstandingRequests[response->seq];
336
337 if (request != nullptr)
338 {
339 if (((ipmbRespNetFn(request->netFn)) == (response->netFn)) &&
340 ((request->rqLun) == (response->rqLun)) &&
341 ((request->rsLun) == (response->rsLun)) &&
342 ((request->cmd) == (response->cmd)))
343 {
344 // match, response is corresponding to previously sent request
345 request->state = ipmbRequestState::matched;
346 request->timer->cancel();
347 request->matchedResponse = std::move(response);
348 }
349 }
350}
351
352void IpmbChannel::processI2cEvent()
353{
354 std::array<uint8_t, ipmbMaxFrameLength> buffer{};
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800355 IPMB_PKT *ipmbPkt = reinterpret_cast<IPMB_PKT *>(buffer.data());
356 IPMB_HEADER *ipmbFrame = &(ipmbPkt->hdr);
Dawid Fryckia642a942018-06-12 10:44:23 -0700357
358 lseek(ipmbi2cSlaveFd, 0, SEEK_SET);
359 int r = read(ipmbi2cSlaveFd, buffer.data(), ipmbMaxFrameLength);
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800360
361 /* Substract first byte len size from total frame length */
362 r--;
363
Dawid Fryckia642a942018-06-12 10:44:23 -0700364 if ((r < ipmbMinFrameLength) || (r > ipmbMaxFrameLength))
365 {
366 goto end;
367 }
368
369 // valiate the frame
370 if (!isFrameValid(ipmbFrame, r))
371 {
372 goto end;
373 }
374
Chen Yugang15185ff2020-09-01 09:20:33 +0800375 // if it is message received from ipmb channel, send out dbus signal
376 if (getChannelType() == ipmbChannelType::ipmb)
Qiang XUbbfd00a2019-06-27 21:10:06 +0800377 {
378 auto ipmbMessageReceived = IpmbRequest();
379 ipmbMessageReceived.i2cToIpmbConstruct(ipmbFrame, r);
Patrick Williams3852f8e2022-07-22 19:26:56 -0500380 sdbusplus::message_t msg =
Qiang XUbbfd00a2019-06-27 21:10:06 +0800381 conn->new_signal(ipmbObj, ipmbDbusIntf, "receiveBroadcast");
382 msg.append(ipmbMessageReceived.netFn, ipmbMessageReceived.cmd,
383 ipmbMessageReceived.data);
384 msg.signal_send();
385 }
386
Dawid Fryckia642a942018-06-12 10:44:23 -0700387 // copy frame to ipmib message buffer
Chen Yugang3e07b9e2020-10-13 16:14:04 +0800388 if (ipmbIsResponse(ipmbFrame))
Dawid Fryckia642a942018-06-12 10:44:23 -0700389 {
390 std::unique_ptr<IpmbResponse> ipmbMessageReceived =
391 std::make_unique<IpmbResponse>();
392
393 ipmbMessageReceived->i2cToIpmbConstruct(ipmbFrame, r);
394
395 // try to match response with outstanding request
396 responseMatch(ipmbMessageReceived);
397 }
398 else
399 {
400 // if command is blocked - respond with 'invalid command'
401 // completion code
402 if (commandFilter)
403 {
404 uint8_t netFn = ipmbNetFnGet(ipmbFrame->Header.Req.rsNetFnLUN);
405 uint8_t cmd = ipmbFrame->Header.Req.cmd;
Qiang XUbbfd00a2019-06-27 21:10:06 +0800406 uint8_t rqSA = ipmbFrame->Header.Req.rqSA;
Dawid Fryckia642a942018-06-12 10:44:23 -0700407
408 if (commandFilter->isBlocked(netFn, cmd))
409 {
410 uint8_t seq = ipmbSeqGet(ipmbFrame->Header.Req.rqSeqLUN);
411 uint8_t lun =
412 ipmbLunFromSeqLunGet(ipmbFrame->Header.Req.rqSeqLUN);
Dawid Fryckia642a942018-06-12 10:44:23 -0700413
414 // prepare generic response
Qiang XUbbfd00a2019-06-27 21:10:06 +0800415 auto ipmbResponse = IpmbResponse(
416 rqSA, ipmbRespNetFn(netFn), lun, ipmbBmcSlaveAddress, seq,
417 ipmbRsLun, cmd, ipmbIpmiInvalidCmd, {});
Dawid Fryckia642a942018-06-12 10:44:23 -0700418
Dawid Frycki8188d762019-04-01 18:03:48 -0700419 auto buffer = ipmbResponse.ipmbToi2cConstruct();
420 if (buffer)
Dawid Fryckia642a942018-06-12 10:44:23 -0700421 {
Qiang XUbbfd00a2019-06-27 21:10:06 +0800422 ipmbSendI2cFrame(buffer);
Dawid Fryckia642a942018-06-12 10:44:23 -0700423 }
424
425 goto end;
426 }
427 }
428
429 auto ipmbMessageReceived = IpmbRequest();
Dawid Fryckia642a942018-06-12 10:44:23 -0700430 ipmbMessageReceived.i2cToIpmbConstruct(ipmbFrame, r);
431
Kumar Thangavel8fe0abe2020-08-19 21:42:23 +0530432 int devId = getDevIndex();
433
Dawid Frycki8188d762019-04-01 18:03:48 -0700434 std::map<std::string, std::variant<int>> options{
Kumar Thangavel8fe0abe2020-08-19 21:42:23 +0530435 {"rqSA", ipmbAddressTo7BitSet(ipmbMessageReceived.rqSA)},
436 {"hostId", devId}};
437
Dawid Frycki8188d762019-04-01 18:03:48 -0700438 using IpmiDbusRspType = std::tuple<uint8_t, uint8_t, uint8_t, uint8_t,
439 std::vector<uint8_t>>;
440 conn->async_method_call(
441 [this, rqLun{ipmbMessageReceived.rqLun},
Qiang XUbbfd00a2019-06-27 21:10:06 +0800442 seq{ipmbMessageReceived.seq}, address{ipmbMessageReceived.rqSA}](
443 const boost::system::error_code &ec,
444 const IpmiDbusRspType &response) {
Dawid Frycki8188d762019-04-01 18:03:48 -0700445 const auto &[netfn, lun, cmd, cc, payload] = response;
446 if (ec)
447 {
448 phosphor::logging::log<phosphor::logging::level::ERR>(
449 "processI2cEvent: error getting response from IPMI");
450 return;
451 }
Dawid Fryckia642a942018-06-12 10:44:23 -0700452
Dawid Frycki8188d762019-04-01 18:03:48 -0700453 uint8_t bmcSlaveAddress = getBmcSlaveAddress();
454
455 if (payload.size() > ipmbMaxDataSize)
456 {
457 phosphor::logging::log<phosphor::logging::level::ERR>(
458 "processI2cEvent: response exceeding maximum size");
459
460 // prepare generic response
461 auto ipmbResponse = IpmbResponse(
Qiang XUbbfd00a2019-06-27 21:10:06 +0800462 address, netfn, rqLun, bmcSlaveAddress, seq, ipmbRsLun,
463 cmd, ipmbIpmiCmdRespNotProvided, {});
Dawid Frycki8188d762019-04-01 18:03:48 -0700464
465 auto buffer = ipmbResponse.ipmbToi2cConstruct();
466 if (buffer)
467 {
Qiang XUbbfd00a2019-06-27 21:10:06 +0800468 ipmbSendI2cFrame(buffer);
Dawid Frycki8188d762019-04-01 18:03:48 -0700469 }
470
471 return;
472 }
473
474 if (!(netfn & ipmbNetFnResponseMask))
475 {
476 // we are not expecting request here
477 phosphor::logging::log<phosphor::logging::level::ERR>(
478 "processI2cEvent: got a request instead of response");
479 return;
480 }
481
482 // if command is not supported, add it to filter
483 if (cc == ipmbIpmiInvalidCmd)
484 {
485 addFilter(ipmbReqNetFnFromRespNetFn(netfn), cmd);
486 }
487
488 // payload is empty after constructor invocation
489 auto ipmbResponse =
Qiang XUbbfd00a2019-06-27 21:10:06 +0800490 IpmbResponse(address, netfn, rqLun, bmcSlaveAddress, seq,
491 lun, cmd, cc, payload);
Dawid Frycki8188d762019-04-01 18:03:48 -0700492
493 auto buffer = ipmbResponse.ipmbToi2cConstruct();
494 if (!buffer)
495 {
496 phosphor::logging::log<phosphor::logging::level::ERR>(
497 "processI2cEvent: error constructing a request");
498 return;
499 }
500
Qiang XUbbfd00a2019-06-27 21:10:06 +0800501 ipmbSendI2cFrame(buffer);
Dawid Frycki8188d762019-04-01 18:03:48 -0700502 },
503 "xyz.openbmc_project.Ipmi.Host", "/xyz/openbmc_project/Ipmi",
504 "xyz.openbmc_project.Ipmi.Server", "execute",
505 ipmbMessageReceived.netFn, ipmbMessageReceived.rsLun,
506 ipmbMessageReceived.cmd, ipmbMessageReceived.data, options);
Dawid Fryckia642a942018-06-12 10:44:23 -0700507 }
508
509end:
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800510 i2cSlaveDescriptor.async_wait(
511 boost::asio::posix::descriptor_base::wait_read,
Dawid Fryckia642a942018-06-12 10:44:23 -0700512 [this](const boost::system::error_code &ec) {
513 if (ec)
514 {
515 phosphor::logging::log<phosphor::logging::level::ERR>(
516 "Error: processI2cEvent()");
517 return;
518 }
519
520 processI2cEvent();
521 });
522}
523
Ed Tanous1486b8a2023-02-28 13:28:59 -0800524IpmbChannel::IpmbChannel(boost::asio::io_context &io,
Dawid Fryckia642a942018-06-12 10:44:23 -0700525 uint8_t ipmbBmcSlaveAddress,
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530526 uint8_t ipmbRqSlaveAddress, uint8_t channelIdx,
Dawid Fryckia642a942018-06-12 10:44:23 -0700527 std::shared_ptr<IpmbCommandFilter> commandFilter) :
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800528 i2cSlaveDescriptor(io),
529 ipmbBmcSlaveAddress(ipmbBmcSlaveAddress),
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530530 ipmbRqSlaveAddress(ipmbRqSlaveAddress), channelIdx(channelIdx),
Dawid Fryckia642a942018-06-12 10:44:23 -0700531 commandFilter(commandFilter)
532{
533}
534
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800535int IpmbChannel::ipmbChannelInit(const char *ipmbI2cSlave)
Dawid Fryckia642a942018-06-12 10:44:23 -0700536{
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800537 // extract bus id from slave path and save
538 std::string ipmbI2cSlaveStr(ipmbI2cSlave);
539 auto findHyphen = ipmbI2cSlaveStr.find("-");
540 std::string busStr = ipmbI2cSlaveStr.substr(findHyphen + 1);
Qiang XU8edcf1a2019-06-14 22:18:15 +0800541 try
542 {
543 ipmbBusId = std::stoi(busStr);
544 }
Patrick Williamsc0dd70d2021-09-03 08:33:48 -0500545 catch (const std::invalid_argument &)
Qiang XU8edcf1a2019-06-14 22:18:15 +0800546 {
547 phosphor::logging::log<phosphor::logging::level::ERR>(
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800548 "ipmbChannelInit: invalid bus id in slave-path config");
Qiang XU8edcf1a2019-06-14 22:18:15 +0800549 return -1;
550 }
551
552 // Check if sysfs has device. If not, enable I2C slave driver by command
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800553 // echo "ipmb-dev 0x1010" > /sys/bus/i2c/devices/i2c-0/new_device
Qiang XU8edcf1a2019-06-14 22:18:15 +0800554 bool hasSysfs = std::filesystem::exists(ipmbI2cSlave);
555 if (!hasSysfs)
556 {
557 std::string deviceFileName =
558 "/sys/bus/i2c/devices/i2c-" + busStr + "/new_device";
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800559 std::string para = "ipmb-dev 0x1010"; // init with BMC addr 0x20
Qiang XU8edcf1a2019-06-14 22:18:15 +0800560 std::fstream deviceFile;
561 deviceFile.open(deviceFileName, std::ios::out);
562 if (!deviceFile.good())
563 {
564 phosphor::logging::log<phosphor::logging::level::ERR>(
565 "ipmbChannelInit: error opening deviceFile");
566 return -1;
567 }
568 deviceFile << para;
569 deviceFile.close();
570 }
571
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800572 // open fd to i2c slave device for read write
573 ipmbi2cSlaveFd = open(ipmbI2cSlave, O_RDWR | O_NONBLOCK | O_CLOEXEC);
Dawid Fryckia642a942018-06-12 10:44:23 -0700574 if (ipmbi2cSlaveFd < 0)
575 {
576 phosphor::logging::log<phosphor::logging::level::ERR>(
577 "ipmbChannelInit: error opening ipmbI2cSlave");
578 return -1;
579 }
580
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800581 i2cSlaveDescriptor.assign(ipmbi2cSlaveFd);
Dawid Fryckia642a942018-06-12 10:44:23 -0700582
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800583 i2cSlaveDescriptor.async_wait(
584 boost::asio::posix::descriptor_base::wait_read,
Dawid Fryckia642a942018-06-12 10:44:23 -0700585 [this](const boost::system::error_code &ec) {
586 if (ec)
587 {
588 phosphor::logging::log<phosphor::logging::level::ERR>(
589 "Error: processI2cEvent()");
590 return;
591 }
592
593 processI2cEvent();
594 });
595
596 return 0;
597}
598
Qiang XU8edcf1a2019-06-14 22:18:15 +0800599int IpmbChannel::ipmbChannelUpdateSlaveAddress(const uint8_t newBmcSlaveAddr)
600{
601 if (ipmbi2cSlaveFd > 0)
602 {
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800603 i2cSlaveDescriptor.close();
Qiang XU8edcf1a2019-06-14 22:18:15 +0800604 close(ipmbi2cSlaveFd);
605 ipmbi2cSlaveFd = 0;
606 }
607
608 // disable old I2C slave driver by command:
609 // echo "0x1010" > /sys/bus/i2c/devices/i2c-0/delete_device
610 std::string deviceFileName;
611 std::string para;
612 std::fstream deviceFile;
613 deviceFileName = "/sys/bus/i2c/devices/i2c-" + std::to_string(ipmbBusId) +
614 "/delete_device";
615 para = "0x1010"; // align with removed ipmb0 definition in dts file
616 deviceFile.open(deviceFileName, std::ios::out);
617 if (!deviceFile.good())
618 {
619 phosphor::logging::log<phosphor::logging::level::ERR>(
620 "ipmbChannelUpdateSlaveAddress: error opening deviceFile to delete "
621 "sysfs");
622 return -1;
623 }
624 deviceFile << para;
625 deviceFile.close();
626
627 // enable new I2C slave driver by command:
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800628 // echo "ipmb-dev 0x1012" > /sys/bus/i2c/devices/i2c-0/new_device
Qiang XU8edcf1a2019-06-14 22:18:15 +0800629 deviceFileName =
630 "/sys/bus/i2c/devices/i2c-" + std::to_string(ipmbBusId) + "/new_device";
631 std::ostringstream hex;
632 uint16_t addr = 0x1000 + (newBmcSlaveAddr >> 1);
633 hex << std::hex << static_cast<uint16_t>(addr);
634 const std::string &addressHexStr = hex.str();
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800635 para = "ipmb-dev 0x" + addressHexStr;
Qiang XU8edcf1a2019-06-14 22:18:15 +0800636 deviceFile.open(deviceFileName, std::ios::out);
637 if (!deviceFile.good())
638 {
639 phosphor::logging::log<phosphor::logging::level::ERR>(
640 "ipmbChannelUpdateSlaveAddress: error opening deviceFile to create "
641 "sysfs");
642 return -1;
643 }
644 deviceFile << para;
645 deviceFile.close();
646
647 // open fd to i2c slave device
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800648 std::string ipmbI2cSlaveStr = "/dev/ipmb-" + std::to_string(ipmbBusId);
649 ipmbi2cSlaveFd = open(ipmbI2cSlaveStr.c_str(), O_RDWR | O_NONBLOCK);
Qiang XU8edcf1a2019-06-14 22:18:15 +0800650 if (ipmbi2cSlaveFd < 0)
651 {
652 phosphor::logging::log<phosphor::logging::level::ERR>(
653 "ipmbChannelInit: error opening ipmbI2cSlave");
654 return -1;
655 }
656
657 // start to receive i2c data as slave
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800658 i2cSlaveDescriptor.assign(ipmbi2cSlaveFd);
659 i2cSlaveDescriptor.async_wait(
660 boost::asio::posix::descriptor_base::wait_read,
Qiang XU8edcf1a2019-06-14 22:18:15 +0800661 [this](const boost::system::error_code &ec) {
662 if (ec)
663 {
664 phosphor::logging::log<phosphor::logging::level::ERR>(
665 "Error: processI2cEvent()");
666 return;
667 }
668
669 processI2cEvent();
670 });
671
Qiang XUbbfd00a2019-06-27 21:10:06 +0800672 ipmbBmcSlaveAddress = newBmcSlaveAddr;
673
Qiang XU8edcf1a2019-06-14 22:18:15 +0800674 return 0;
675}
676
677uint8_t IpmbChannel::getBusId()
678{
679 return ipmbBusId;
680}
681
Dawid Fryckia642a942018-06-12 10:44:23 -0700682uint8_t IpmbChannel::getBmcSlaveAddress()
683{
684 return ipmbBmcSlaveAddress;
685}
686
687uint8_t IpmbChannel::getRqSlaveAddress()
688{
689 return ipmbRqSlaveAddress;
690}
691
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530692uint8_t IpmbChannel::getDevIndex()
693{
694 return channelIdx >> 2;
695}
696
697uint8_t IpmbChannel::getChannelIdx()
698{
699 return channelIdx;
700}
701
Dawid Fryckia642a942018-06-12 10:44:23 -0700702ipmbChannelType IpmbChannel::getChannelType()
703{
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530704 return static_cast<ipmbChannelType>((channelIdx & 3));
Dawid Fryckia642a942018-06-12 10:44:23 -0700705}
706
707void IpmbChannel::addFilter(const uint8_t respNetFn, const uint8_t cmd)
708{
709 if (commandFilter)
710 {
711 commandFilter->addFilter(respNetFn, cmd);
712 }
713}
714
715std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
716 IpmbChannel::requestAdd(boost::asio::yield_context &yield,
717 std::shared_ptr<IpmbRequest> request)
718{
719 makeRequestValid(request);
720
721 std::vector<uint8_t> buffer(0);
722 if (request->ipmbToi2cConstruct(buffer) != 0)
723 {
724 return returnStatus(ipmbResponseStatus::error);
725 }
726
727 for (int i = 0; i < ipmbNumberOfTries; i++)
728 {
729 boost::system::error_code ec;
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800730 int i2cRetryCnt = 0;
Dawid Fryckia642a942018-06-12 10:44:23 -0700731
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800732 for (; i2cRetryCnt < ipmbI2cNumberOfRetries; i2cRetryCnt++)
Dawid Fryckia642a942018-06-12 10:44:23 -0700733 {
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800734 boost::asio::async_write(i2cSlaveDescriptor,
735 boost::asio::buffer(buffer), yield[ec]);
Dawid Fryckia642a942018-06-12 10:44:23 -0700736
737 if (ec)
738 {
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800739 continue; // retry
Dawid Fryckia642a942018-06-12 10:44:23 -0700740 }
741 break;
742 }
743
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800744 if (i2cRetryCnt == ipmbI2cNumberOfRetries)
745 {
Qiang XUbbfd00a2019-06-27 21:10:06 +0800746 std::string msgToLog =
747 "requestAdd: Sent to I2C failed after retries."
748 " busId=" +
749 std::to_string(ipmbBusId) + ", error=" + ec.message();
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800750 phosphor::logging::log<phosphor::logging::level::INFO>(
Qiang XUbbfd00a2019-06-27 21:10:06 +0800751 msgToLog.c_str());
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800752 }
753
Dawid Fryckia642a942018-06-12 10:44:23 -0700754 request->timer->expires_after(
755 std::chrono::milliseconds(ipmbRequestRetryTimeout));
756 request->timer->async_wait(yield[ec]);
757
758 if (ec && ec != boost::asio::error::operation_aborted)
759 {
760 // unexpected error - invalidate request and return generic error
761 phosphor::logging::log<phosphor::logging::level::ERR>(
762 "requestAdd: async_wait error");
763 makeRequestInvalid(*request);
764 return returnStatus(ipmbResponseStatus::error);
765 }
766
767 if (request->state == ipmbRequestState::matched)
768 {
769 // matched response, send it to client application
770 makeRequestInvalid(*request);
771 return request->returnMatchedResponse();
772 }
773 }
774
775 makeRequestInvalid(*request);
776 return returnStatus(ipmbResponseStatus::timeout);
777}
778
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530779static IpmbChannel *getChannel(uint8_t reqChannel)
Dawid Fryckia642a942018-06-12 10:44:23 -0700780{
781 auto channel =
782 std::find_if(ipmbChannels.begin(), ipmbChannels.end(),
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530783 [reqChannel](IpmbChannel &channel) {
784 return channel.getChannelIdx() == reqChannel;
Dawid Fryckia642a942018-06-12 10:44:23 -0700785 });
786 if (channel != ipmbChannels.end())
787 {
788 return &(*channel);
789 }
790
791 return nullptr;
792}
793
794static int initializeChannels()
795{
796 std::shared_ptr<IpmbCommandFilter> commandFilter =
797 std::make_shared<IpmbCommandFilter>();
798
Amithash Prasad314862d2019-03-26 11:14:03 -0700799 constexpr const char *configFilePath =
800 "/usr/share/ipmbbridge/ipmb-channels.json";
801 std::ifstream configFile(configFilePath);
802 if (!configFile.is_open())
Dawid Fryckia642a942018-06-12 10:44:23 -0700803 {
Amithash Prasad314862d2019-03-26 11:14:03 -0700804 phosphor::logging::log<phosphor::logging::level::ERR>(
805 "initializeChannels: Cannot open config path");
806 return -1;
807 }
808 try
809 {
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530810 uint8_t devIndex = 0;
Amithash Prasad314862d2019-03-26 11:14:03 -0700811 auto data = nlohmann::json::parse(configFile, nullptr);
812 for (const auto &channelConfig : data["channels"])
Dawid Fryckia642a942018-06-12 10:44:23 -0700813 {
Amithash Prasad314862d2019-03-26 11:14:03 -0700814 const std::string &typeConfig = channelConfig["type"];
Amithash Prasad314862d2019-03-26 11:14:03 -0700815 const std::string &slavePath = channelConfig["slave-path"];
816 uint8_t bmcAddr = channelConfig["bmc-addr"];
817 uint8_t reqAddr = channelConfig["remote-addr"];
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530818
Amithash Prasad314862d2019-03-26 11:14:03 -0700819 ipmbChannelType type = ipmbChannelTypeMap.at(typeConfig);
820
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530821 if (channelConfig.contains("devIndex"))
822 {
823 devIndex = channelConfig["devIndex"];
824 }
825
826 auto channel = ipmbChannels.emplace(
827 ipmbChannels.end(), io, bmcAddr, reqAddr,
828 ((devIndex << 2) | static_cast<uint8_t>(type)), commandFilter);
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800829 if (channel->ipmbChannelInit(slavePath.c_str()) < 0)
Amithash Prasad314862d2019-03-26 11:14:03 -0700830 {
831 phosphor::logging::log<phosphor::logging::level::ERR>(
832 "initializeChannels: channel initialization failed");
833 return -1;
834 }
Dawid Fryckia642a942018-06-12 10:44:23 -0700835 }
836 }
Patrick Williamsc0dd70d2021-09-03 08:33:48 -0500837 catch (const nlohmann::json::exception &e)
Amithash Prasad314862d2019-03-26 11:14:03 -0700838 {
839 phosphor::logging::log<phosphor::logging::level::ERR>(
840 "initializeChannels: Error parsing config file");
841 return -1;
842 }
Patrick Williamsc0dd70d2021-09-03 08:33:48 -0500843 catch (const std::out_of_range &e)
Amithash Prasad314862d2019-03-26 11:14:03 -0700844 {
845 phosphor::logging::log<phosphor::logging::level::ERR>(
846 "initializeChannels: Error invalid type");
847 return -1;
848 }
Dawid Fryckia642a942018-06-12 10:44:23 -0700849 return 0;
850}
851
Dawid Fryckia642a942018-06-12 10:44:23 -0700852auto ipmbHandleRequest = [](boost::asio::yield_context yield,
853 uint8_t reqChannel, uint8_t netfn, uint8_t lun,
854 uint8_t cmd, std::vector<uint8_t> dataReceived) {
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530855 IpmbChannel *channel = getChannel(reqChannel);
856
Dawid Fryckia642a942018-06-12 10:44:23 -0700857 if (channel == nullptr)
858 {
859 phosphor::logging::log<phosphor::logging::level::ERR>(
860 "ipmbHandleRequest: requested channel does not exist");
861 return returnStatus(ipmbResponseStatus::invalid_param);
862 }
863
864 // check outstanding request list for valid sequence number
865 uint8_t seqNum = 0;
866 bool seqValid = channel->seqNumGet(seqNum);
867 if (!seqValid)
868 {
869 phosphor::logging::log<phosphor::logging::level::WARNING>(
870 "ipmbHandleRequest: cannot add more requests to the list");
871 return returnStatus(ipmbResponseStatus::busy);
872 }
873
874 uint8_t bmcSlaveAddress = channel->getBmcSlaveAddress();
875 uint8_t rqSlaveAddress = channel->getRqSlaveAddress();
876
877 // construct the request to add it to outstanding request list
878 std::shared_ptr<IpmbRequest> request = std::make_shared<IpmbRequest>(
879 rqSlaveAddress, netfn, ipmbRsLun, bmcSlaveAddress, seqNum, lun, cmd,
880 dataReceived);
881
882 if (!request->timer)
883 {
884 phosphor::logging::log<phosphor::logging::level::ERR>(
885 "ipmbHandleRequest: timer object does not exist");
886 return returnStatus(ipmbResponseStatus::error);
887 }
888
889 return channel->requestAdd(yield, request);
890};
891
Qiang XU8edcf1a2019-06-14 22:18:15 +0800892void addUpdateSlaveAddrHandler()
893{
894 // callback to handle dbus signal of updating slave addr
Patrick Williams3852f8e2022-07-22 19:26:56 -0500895 std::function<void(sdbusplus::message_t &)> updateSlaveAddrHandler =
896 [](sdbusplus::message_t &message) {
Qiang XU8edcf1a2019-06-14 22:18:15 +0800897 uint8_t reqChannel, busId, slaveAddr;
898
899 // valid source of signal, check whether from multi-node manager
900 std::string pathName = message.get_path();
901 if (pathName != "/xyz/openbmc_project/MultiNode/Status")
902 {
903 phosphor::logging::log<phosphor::logging::level::ERR>(
904 "addUpdateSlaveAddrHandler: invalid obj path");
905 return;
906 }
907
908 message.read(reqChannel, busId, slaveAddr);
909
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530910 IpmbChannel *channel = getChannel(reqChannel);
911
Qiang XU8edcf1a2019-06-14 22:18:15 +0800912 if (channel == nullptr ||
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530913 channel->getChannelType() != ipmbChannelType::ipmb)
Qiang XU8edcf1a2019-06-14 22:18:15 +0800914 {
915 phosphor::logging::log<phosphor::logging::level::ERR>(
916 "addUpdateSlaveAddrHandler: invalid channel");
917 return;
918 }
919 if (busId != channel->getBusId())
920 {
921 phosphor::logging::log<phosphor::logging::level::ERR>(
922 "addUpdateSlaveAddrHandler: invalid busId");
923 return;
924 }
925 if (channel->getBmcSlaveAddress() == slaveAddr)
926 {
927 phosphor::logging::log<phosphor::logging::level::INFO>(
928 "addUpdateSlaveAddrHandler: channel bmc slave addr is "
929 "unchanged, do nothing");
930 return;
931 }
932
933 channel->ipmbChannelUpdateSlaveAddress(slaveAddr);
934 };
935
Patrick Williams3852f8e2022-07-22 19:26:56 -0500936 static auto match = std::make_unique<sdbusplus::bus::match_t>(
937 static_cast<sdbusplus::bus_t &>(*conn),
Qiang XU8edcf1a2019-06-14 22:18:15 +0800938 "type='signal',member='updateBmcSlaveAddr',", updateSlaveAddrHandler);
939}
940
Qiang XUbbfd00a2019-06-27 21:10:06 +0800941void addSendBroadcastHandler()
942{
943 // callback to handle dbus signal of sending broadcast message
Patrick Williams3852f8e2022-07-22 19:26:56 -0500944 std::function<void(sdbusplus::message_t &)> sendBroadcastHandler =
945 [](sdbusplus::message_t &message) {
Qiang XUbbfd00a2019-06-27 21:10:06 +0800946 uint8_t reqChannel, netFn, lun, cmd;
947 std::vector<uint8_t> dataReceived;
948 message.read(reqChannel, netFn, lun, cmd, dataReceived);
949
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530950 IpmbChannel *channel = getChannel(reqChannel);
951
Qiang XUbbfd00a2019-06-27 21:10:06 +0800952 if (channel == nullptr)
953 {
954 phosphor::logging::log<phosphor::logging::level::ERR>(
955 "addSendBroadcastMsgHandler: requested channel does not "
956 "exist");
957 return;
958 }
959
960 uint8_t bmcSlaveAddress = channel->getBmcSlaveAddress();
961 uint8_t seqNum = 0; // seqNum is not used in broadcast msg
962 uint8_t targetAddr = broadcastAddress;
963
964 std::shared_ptr<IpmbRequest> request =
965 std::make_shared<IpmbRequest>(targetAddr, netFn, ipmbRsLun,
966 bmcSlaveAddress, seqNum, lun, cmd,
967 dataReceived);
968
969 std::shared_ptr<std::vector<uint8_t>> buffer =
970 std::make_shared<std::vector<uint8_t>>();
971
972 if (request->ipmbToi2cConstruct(*buffer) != 0)
973 {
974 return;
975 }
976
977 channel->ipmbSendI2cFrame(buffer);
978 };
979
Patrick Williams3852f8e2022-07-22 19:26:56 -0500980 static auto match = std::make_unique<sdbusplus::bus::match_t>(
981 static_cast<sdbusplus::bus_t &>(*conn),
Qiang XUbbfd00a2019-06-27 21:10:06 +0800982 "type='signal',member='sendBroadcast',", sendBroadcastHandler);
983}
984
Dawid Fryckia642a942018-06-12 10:44:23 -0700985/**
986 * @brief Main
987 */
988int main(int argc, char *argv[])
989{
990 conn->request_name(ipmbBus);
991
992 auto server = sdbusplus::asio::object_server(conn);
993
Dawid Fryckia642a942018-06-12 10:44:23 -0700994 std::shared_ptr<sdbusplus::asio::dbus_interface> ipmbIface =
995 server.add_interface(ipmbObj, ipmbDbusIntf);
996
Dawid Fryckia642a942018-06-12 10:44:23 -0700997 ipmbIface->register_method("sendRequest", std::move(ipmbHandleRequest));
Dawid Fryckia642a942018-06-12 10:44:23 -0700998 ipmbIface->initialize();
999
1000 if (initializeChannels() < 0)
1001 {
1002 phosphor::logging::log<phosphor::logging::level::ERR>(
1003 "Error initializeChannels");
1004 return -1;
1005 }
1006
Qiang XU8edcf1a2019-06-14 22:18:15 +08001007 addUpdateSlaveAddrHandler();
1008
Qiang XUbbfd00a2019-06-27 21:10:06 +08001009 addSendBroadcastHandler();
1010
Dawid Fryckia642a942018-06-12 10:44:23 -07001011 io.run();
1012 return 0;
1013}