blob: 366707f6fa77412b1efbbc457cfbf47811004386 [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>
Jason M. Bills7867cd72023-03-29 07:58:02 -070026#include <list>
Amithash Prasad314862d2019-03-26 11:14:03 -070027#include <nlohmann/json.hpp>
Dawid Fryckia642a942018-06-12 10:44:23 -070028#include <phosphor-logging/log.hpp>
29#include <tuple>
Amithash Prasad314862d2019-03-26 11:14:03 -070030#include <unordered_map>
Dawid Fryckia642a942018-06-12 10:44:23 -070031
Dawid Fryckia642a942018-06-12 10:44:23 -070032/**
33 * @brief Dbus
34 */
35static constexpr const char *ipmbBus = "xyz.openbmc_project.Ipmi.Channel.Ipmb";
36static constexpr const char *ipmbObj = "/xyz/openbmc_project/Ipmi/Channel/Ipmb";
Dawid Fryckia642a942018-06-12 10:44:23 -070037static constexpr const char *ipmbDbusIntf = "org.openbmc.Ipmb";
38
Ed Tanous1486b8a2023-02-28 13:28:59 -080039boost::asio::io_context io;
Dawid Fryckia642a942018-06-12 10:44:23 -070040auto conn = std::make_shared<sdbusplus::asio::connection>(io);
41
Dawid Fryckia642a942018-06-12 10:44:23 -070042static std::list<IpmbChannel> ipmbChannels;
Amithash Prasad314862d2019-03-26 11:14:03 -070043static const std::unordered_map<std::string, ipmbChannelType>
44 ipmbChannelTypeMap = {{"me", ipmbChannelType::me},
45 {"ipmb", ipmbChannelType::ipmb}};
Dawid Fryckia642a942018-06-12 10:44:23 -070046
47/**
48 * @brief Ipmb request class methods
49 */
50IpmbRequest::IpmbRequest()
51{
52 data.reserve(ipmbMaxDataSize);
53}
54
55IpmbRequest::IpmbRequest(uint8_t address, uint8_t netFn, uint8_t rsLun,
56 uint8_t rqSA, uint8_t seq, uint8_t rqLun, uint8_t cmd,
Dawid Frycki8188d762019-04-01 18:03:48 -070057 const std::vector<uint8_t> &inputData) :
Dawid Fryckia642a942018-06-12 10:44:23 -070058 address(address),
59 netFn(netFn), rsLun(rsLun), rqSA(rqSA), seq(seq), rqLun(rqLun), cmd(cmd),
60 timer(io)
61{
62 data.reserve(ipmbMaxDataSize);
63 state = ipmbRequestState::invalid;
64
65 if (inputData.size() > 0)
66 {
67 data = std::move(inputData);
68 }
69}
70
Dawid Fryckia642a942018-06-12 10:44:23 -070071void IpmbRequest::i2cToIpmbConstruct(IPMB_HEADER *ipmbBuffer,
72 size_t bufferLength)
73{
74 // constructing ipmb request from i2c buffer
75 netFn = ipmbNetFnGet(ipmbBuffer->Header.Req.rsNetFnLUN);
76 rsLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Req.rsNetFnLUN);
77 rqSA = ipmbBuffer->Header.Req.rqSA;
78 seq = ipmbSeqGet(ipmbBuffer->Header.Req.rqSeqLUN);
79 rqLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Req.rqSeqLUN);
80 cmd = ipmbBuffer->Header.Req.cmd;
81
82 size_t dataLength =
83 bufferLength - (ipmbConnectionHeaderLength +
84 ipmbRequestDataHeaderLength + ipmbChecksumSize);
85
86 if (dataLength > 0)
87 {
88 data.insert(data.end(), ipmbBuffer->Header.Req.data,
89 &ipmbBuffer->Header.Req.data[dataLength]);
90 }
91}
92
93int IpmbRequest::ipmbToi2cConstruct(std::vector<uint8_t> &buffer)
94{
Vijay Khemka37a7eac2019-12-06 13:52:28 -080095 /* Add one byte for length byte as per required by driver */
96 size_t bufferLength = 1 + data.size() + ipmbRequestDataHeaderLength +
Dawid Fryckia642a942018-06-12 10:44:23 -070097 ipmbConnectionHeaderLength + ipmbChecksumSize;
98
99 if (bufferLength > ipmbMaxFrameLength)
100 {
101 return -1;
102 }
103
104 buffer.resize(bufferLength);
105 static_assert(ipmbMaxFrameLength >= sizeof(IPMB_HEADER));
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800106 IPMB_PKT *ipmbPkt = reinterpret_cast<IPMB_PKT *>(buffer.data());
107 ipmbPkt->len = bufferLength - 1;
108 IPMB_HEADER *ipmbBuffer = &(ipmbPkt->hdr);
Dawid Fryckia642a942018-06-12 10:44:23 -0700109
110 // constructing buffer from ipmb request
111 ipmbBuffer->Header.Req.address = address;
112 ipmbBuffer->Header.Req.rsNetFnLUN = ipmbNetFnLunSet(netFn, rsLun);
113 ipmbBuffer->Header.Req.rqSA = rqSA;
114 ipmbBuffer->Header.Req.rqSeqLUN = ipmbSeqLunSet(seq, rqLun);
115 ipmbBuffer->Header.Req.cmd = cmd;
116
Qiang XUbbfd00a2019-06-27 21:10:06 +0800117 ipmbBuffer->Header.Req.checksum1 = ipmbChecksumCompute(
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800118 (uint8_t *)ipmbBuffer, ipmbConnectionHeaderLength - ipmbChecksumSize);
Dawid Fryckia642a942018-06-12 10:44:23 -0700119
120 if (data.size() > 0)
121 {
122 std::copy(data.begin(), data.end(), ipmbBuffer->Header.Req.data);
123 }
124
125 buffer[bufferLength - ipmbChecksumSize] =
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800126 ipmbChecksumCompute((uint8_t *)ipmbBuffer + ipmbChecksum2StartOffset,
Dawid Fryckia642a942018-06-12 10:44:23 -0700127 (ipmbRequestDataHeaderLength + data.size()));
128
129 return 0;
130}
131
132std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
133 IpmbRequest::returnMatchedResponse()
134{
135 return std::make_tuple(
136 static_cast<int>(ipmbResponseStatus::success), matchedResponse->netFn,
137 matchedResponse->rsLun, matchedResponse->cmd,
138 matchedResponse->completionCode, matchedResponse->data);
139}
140
141static std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
142 returnStatus(ipmbResponseStatus status)
143{
144 // we only want to send status here, other fields are not relevant
145 return std::make_tuple(static_cast<int>(status), 0, 0, 0, 0,
146 std::vector<uint8_t>(0));
147}
148
Dawid Fryckia642a942018-06-12 10:44:23 -0700149/**
150 * @brief Ipmb response class methods
151 */
152IpmbResponse::IpmbResponse()
153{
154 data.reserve(ipmbMaxDataSize);
155}
156
157IpmbResponse::IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun,
158 uint8_t rsSA, uint8_t seq, uint8_t rsLun,
159 uint8_t cmd, uint8_t completionCode,
Dawid Frycki8188d762019-04-01 18:03:48 -0700160 const std::vector<uint8_t> &inputData) :
Dawid Fryckia642a942018-06-12 10:44:23 -0700161 address(address),
162 netFn(netFn), rqLun(rqLun), rsSA(rsSA), seq(seq), rsLun(rsLun), cmd(cmd),
163 completionCode(completionCode)
164{
165 data.reserve(ipmbMaxDataSize);
166
167 if (inputData.size() > 0)
168 {
169 data = std::move(inputData);
170 }
171}
172
173void IpmbResponse::i2cToIpmbConstruct(IPMB_HEADER *ipmbBuffer,
174 size_t bufferLength)
175{
176 netFn = ipmbNetFnGet(ipmbBuffer->Header.Resp.rqNetFnLUN);
177 rqLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Resp.rqNetFnLUN);
178 rsSA = ipmbBuffer->Header.Resp.rsSA;
179 seq = ipmbSeqGet(ipmbBuffer->Header.Resp.rsSeqLUN);
180 rsLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Resp.rsSeqLUN);
181 cmd = ipmbBuffer->Header.Resp.cmd;
182 completionCode = ipmbBuffer->Header.Resp.completionCode;
183
184 size_t dataLength =
185 bufferLength - (ipmbConnectionHeaderLength +
186 ipmbResponseDataHeaderLength + ipmbChecksumSize);
187
188 if (dataLength > 0)
189 {
190 data.insert(data.end(), ipmbBuffer->Header.Resp.data,
191 &ipmbBuffer->Header.Resp.data[dataLength]);
192 }
193}
194
Dawid Frycki8188d762019-04-01 18:03:48 -0700195std::shared_ptr<std::vector<uint8_t>> IpmbResponse::ipmbToi2cConstruct()
Dawid Fryckia642a942018-06-12 10:44:23 -0700196{
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800197 /* Add one byte for length byte as per required by driver */
198 size_t bufferLength = 1 + data.size() + ipmbResponseDataHeaderLength +
Dawid Fryckia642a942018-06-12 10:44:23 -0700199 ipmbConnectionHeaderLength + ipmbChecksumSize;
200
201 if (bufferLength > ipmbMaxFrameLength)
202 {
Dawid Frycki8188d762019-04-01 18:03:48 -0700203 return nullptr;
Dawid Fryckia642a942018-06-12 10:44:23 -0700204 }
205
Dawid Frycki8188d762019-04-01 18:03:48 -0700206 std::shared_ptr<std::vector<uint8_t>> buffer =
207 std::make_shared<std::vector<uint8_t>>(bufferLength);
208
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800209 IPMB_PKT *ipmbPkt = reinterpret_cast<IPMB_PKT *>(buffer->data());
210 ipmbPkt->len = bufferLength - 1;
211 IPMB_HEADER *ipmbBuffer = &(ipmbPkt->hdr);
Dawid Fryckia642a942018-06-12 10:44:23 -0700212
213 ipmbBuffer->Header.Resp.address = address;
214 ipmbBuffer->Header.Resp.rqNetFnLUN = ipmbNetFnLunSet(netFn, rqLun);
215 ipmbBuffer->Header.Resp.rsSA = rsSA;
216 ipmbBuffer->Header.Resp.rsSeqLUN = ipmbSeqLunSet(seq, rsLun);
217 ipmbBuffer->Header.Resp.cmd = cmd;
218 ipmbBuffer->Header.Resp.completionCode = completionCode;
219
220 ipmbBuffer->Header.Resp.checksum1 = ipmbChecksumCompute(
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800221 (uint8_t *)ipmbBuffer, ipmbConnectionHeaderLength - ipmbChecksumSize);
Dawid Fryckia642a942018-06-12 10:44:23 -0700222
223 if (data.size() > 0)
224 {
225 std::copy(data.begin(), data.end(), ipmbBuffer->Header.Resp.data);
226 }
227
Dawid Frycki8188d762019-04-01 18:03:48 -0700228 (*buffer)[bufferLength - ipmbChecksumSize] =
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800229 ipmbChecksumCompute((uint8_t *)ipmbBuffer + ipmbChecksum2StartOffset,
Dawid Fryckia642a942018-06-12 10:44:23 -0700230 (ipmbResponseDataHeaderLength + data.size()));
231
Dawid Frycki8188d762019-04-01 18:03:48 -0700232 return buffer;
Dawid Fryckia642a942018-06-12 10:44:23 -0700233}
234
235bool IpmbCommandFilter::isBlocked(const uint8_t reqNetFn, const uint8_t cmd)
236{
237 auto blockedCmd = unhandledCommands.find({reqNetFn, cmd});
238
239 if (blockedCmd != unhandledCommands.end())
240 {
241 return true;
242 }
243
244 return false;
245}
246
247void IpmbCommandFilter::addFilter(const uint8_t reqNetFn, const uint8_t cmd)
248{
249 if (unhandledCommands.insert({reqNetFn, cmd}).second)
250 {
251 phosphor::logging::log<phosphor::logging::level::INFO>(
252 "addFilter: added command to filter",
253 phosphor::logging::entry("netFn = %d", reqNetFn),
254 phosphor::logging::entry("cmd = %d", cmd));
255 }
256}
257
258/**
259 * @brief Ipmb channel
260 */
Qiang XUbbfd00a2019-06-27 21:10:06 +0800261void IpmbChannel::ipmbSendI2cFrame(std::shared_ptr<std::vector<uint8_t>> buffer,
Dawid Fryckia642a942018-06-12 10:44:23 -0700262 size_t retriesAttempted = 0)
263{
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800264 IPMB_PKT *ipmbPkt = reinterpret_cast<IPMB_PKT *>(buffer->data());
265 uint8_t targetAddr = ipmbIsResponse(&(ipmbPkt->hdr))
266 ? ipmbPkt->hdr.Header.Resp.address
267 : ipmbPkt->hdr.Header.Req.address;
268 boost::asio::async_write(
269 i2cSlaveDescriptor, boost::asio::buffer(*buffer),
270 [this, buffer, retriesAttempted,
271 targetAddr](const boost::system::error_code &ec, size_t bytesSent) {
272 if (ec)
Dawid Fryckia642a942018-06-12 10:44:23 -0700273 {
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800274 size_t currentRetryCnt = retriesAttempted;
275
276 if (currentRetryCnt > ipmbI2cNumberOfRetries)
277 {
278 std::string msgToLog =
279 "ipmbSendI2cFrame: send to I2C failed after retries."
280 " busId=" +
281 std::to_string(ipmbBusId) +
282 ", targetAddr=" + std::to_string(targetAddr) +
283 ", error=" + ec.message();
284 phosphor::logging::log<phosphor::logging::level::ERR>(
285 msgToLog.c_str());
286 return;
287 }
288 currentRetryCnt++;
289 ipmbSendI2cFrame(buffer, currentRetryCnt);
Dawid Fryckia642a942018-06-12 10:44:23 -0700290 }
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800291 });
Dawid Fryckia642a942018-06-12 10:44:23 -0700292}
293
294/**
295 * @brief Ipmb Outstanding Requests
296 */
297void IpmbChannel::makeRequestInvalid(IpmbRequest &request)
298{
299 // change request state to invalid and remove it from outstanding requests
300 // list
301 request.state = ipmbRequestState::invalid;
302 outstandingRequests[request.seq] = nullptr;
303}
304
305void IpmbChannel::makeRequestValid(std::shared_ptr<IpmbRequest> request)
306{
307 // change request state to valid and add it to outstanding requests list
308 request->state = ipmbRequestState::valid;
309 outstandingRequests[request->seq] = request;
310}
311
312bool IpmbChannel::seqNumGet(uint8_t &seq)
313{
314 static uint8_t seqNum = 0;
315
316 for (int i = 0; i < ipmbMaxOutstandingRequestsCount; i++)
317 {
318 seqNum = ++seqNum & ipmbSeqMask;
319 if (seqNum == ipmbMaxOutstandingRequestsCount)
320 {
321 seqNum = 0;
322 }
323
324 if (outstandingRequests[seqNum] == nullptr)
325 {
326 seq = seqNum;
327 return true;
328 }
329 }
330
331 return false;
332}
333
334void IpmbChannel::responseMatch(std::unique_ptr<IpmbResponse> &response)
335{
336 std::shared_ptr<IpmbRequest> request = outstandingRequests[response->seq];
337
338 if (request != nullptr)
339 {
340 if (((ipmbRespNetFn(request->netFn)) == (response->netFn)) &&
341 ((request->rqLun) == (response->rqLun)) &&
342 ((request->rsLun) == (response->rsLun)) &&
343 ((request->cmd) == (response->cmd)))
344 {
345 // match, response is corresponding to previously sent request
346 request->state = ipmbRequestState::matched;
347 request->timer->cancel();
348 request->matchedResponse = std::move(response);
349 }
350 }
351}
352
353void IpmbChannel::processI2cEvent()
354{
355 std::array<uint8_t, ipmbMaxFrameLength> buffer{};
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800356 IPMB_PKT *ipmbPkt = reinterpret_cast<IPMB_PKT *>(buffer.data());
357 IPMB_HEADER *ipmbFrame = &(ipmbPkt->hdr);
Dawid Fryckia642a942018-06-12 10:44:23 -0700358
359 lseek(ipmbi2cSlaveFd, 0, SEEK_SET);
360 int r = read(ipmbi2cSlaveFd, buffer.data(), ipmbMaxFrameLength);
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800361
362 /* Substract first byte len size from total frame length */
363 r--;
364
Dawid Fryckia642a942018-06-12 10:44:23 -0700365 if ((r < ipmbMinFrameLength) || (r > ipmbMaxFrameLength))
366 {
367 goto end;
368 }
369
370 // valiate the frame
371 if (!isFrameValid(ipmbFrame, r))
372 {
373 goto end;
374 }
375
Chen Yugang15185ff2020-09-01 09:20:33 +0800376 // if it is message received from ipmb channel, send out dbus signal
377 if (getChannelType() == ipmbChannelType::ipmb)
Qiang XUbbfd00a2019-06-27 21:10:06 +0800378 {
379 auto ipmbMessageReceived = IpmbRequest();
380 ipmbMessageReceived.i2cToIpmbConstruct(ipmbFrame, r);
Patrick Williams3852f8e2022-07-22 19:26:56 -0500381 sdbusplus::message_t msg =
Qiang XUbbfd00a2019-06-27 21:10:06 +0800382 conn->new_signal(ipmbObj, ipmbDbusIntf, "receiveBroadcast");
383 msg.append(ipmbMessageReceived.netFn, ipmbMessageReceived.cmd,
384 ipmbMessageReceived.data);
385 msg.signal_send();
386 }
387
Dawid Fryckia642a942018-06-12 10:44:23 -0700388 // copy frame to ipmib message buffer
Chen Yugang3e07b9e2020-10-13 16:14:04 +0800389 if (ipmbIsResponse(ipmbFrame))
Dawid Fryckia642a942018-06-12 10:44:23 -0700390 {
391 std::unique_ptr<IpmbResponse> ipmbMessageReceived =
392 std::make_unique<IpmbResponse>();
393
394 ipmbMessageReceived->i2cToIpmbConstruct(ipmbFrame, r);
395
396 // try to match response with outstanding request
397 responseMatch(ipmbMessageReceived);
398 }
399 else
400 {
401 // if command is blocked - respond with 'invalid command'
402 // completion code
403 if (commandFilter)
404 {
405 uint8_t netFn = ipmbNetFnGet(ipmbFrame->Header.Req.rsNetFnLUN);
406 uint8_t cmd = ipmbFrame->Header.Req.cmd;
Qiang XUbbfd00a2019-06-27 21:10:06 +0800407 uint8_t rqSA = ipmbFrame->Header.Req.rqSA;
Dawid Fryckia642a942018-06-12 10:44:23 -0700408
409 if (commandFilter->isBlocked(netFn, cmd))
410 {
411 uint8_t seq = ipmbSeqGet(ipmbFrame->Header.Req.rqSeqLUN);
412 uint8_t lun =
413 ipmbLunFromSeqLunGet(ipmbFrame->Header.Req.rqSeqLUN);
Dawid Fryckia642a942018-06-12 10:44:23 -0700414
415 // prepare generic response
Qiang XUbbfd00a2019-06-27 21:10:06 +0800416 auto ipmbResponse = IpmbResponse(
417 rqSA, ipmbRespNetFn(netFn), lun, ipmbBmcSlaveAddress, seq,
418 ipmbRsLun, cmd, ipmbIpmiInvalidCmd, {});
Dawid Fryckia642a942018-06-12 10:44:23 -0700419
Dawid Frycki8188d762019-04-01 18:03:48 -0700420 auto buffer = ipmbResponse.ipmbToi2cConstruct();
421 if (buffer)
Dawid Fryckia642a942018-06-12 10:44:23 -0700422 {
Qiang XUbbfd00a2019-06-27 21:10:06 +0800423 ipmbSendI2cFrame(buffer);
Dawid Fryckia642a942018-06-12 10:44:23 -0700424 }
425
426 goto end;
427 }
428 }
429
430 auto ipmbMessageReceived = IpmbRequest();
Dawid Fryckia642a942018-06-12 10:44:23 -0700431 ipmbMessageReceived.i2cToIpmbConstruct(ipmbFrame, r);
432
Kumar Thangavel8fe0abe2020-08-19 21:42:23 +0530433 int devId = getDevIndex();
434
Dawid Frycki8188d762019-04-01 18:03:48 -0700435 std::map<std::string, std::variant<int>> options{
Kumar Thangavel8fe0abe2020-08-19 21:42:23 +0530436 {"rqSA", ipmbAddressTo7BitSet(ipmbMessageReceived.rqSA)},
437 {"hostId", devId}};
438
Dawid Frycki8188d762019-04-01 18:03:48 -0700439 using IpmiDbusRspType = std::tuple<uint8_t, uint8_t, uint8_t, uint8_t,
440 std::vector<uint8_t>>;
441 conn->async_method_call(
442 [this, rqLun{ipmbMessageReceived.rqLun},
Qiang XUbbfd00a2019-06-27 21:10:06 +0800443 seq{ipmbMessageReceived.seq}, address{ipmbMessageReceived.rqSA}](
444 const boost::system::error_code &ec,
445 const IpmiDbusRspType &response) {
Dawid Frycki8188d762019-04-01 18:03:48 -0700446 const auto &[netfn, lun, cmd, cc, payload] = response;
447 if (ec)
448 {
449 phosphor::logging::log<phosphor::logging::level::ERR>(
450 "processI2cEvent: error getting response from IPMI");
451 return;
452 }
Dawid Fryckia642a942018-06-12 10:44:23 -0700453
Dawid Frycki8188d762019-04-01 18:03:48 -0700454 uint8_t bmcSlaveAddress = getBmcSlaveAddress();
455
456 if (payload.size() > ipmbMaxDataSize)
457 {
458 phosphor::logging::log<phosphor::logging::level::ERR>(
459 "processI2cEvent: response exceeding maximum size");
460
461 // prepare generic response
462 auto ipmbResponse = IpmbResponse(
Qiang XUbbfd00a2019-06-27 21:10:06 +0800463 address, netfn, rqLun, bmcSlaveAddress, seq, ipmbRsLun,
464 cmd, ipmbIpmiCmdRespNotProvided, {});
Dawid Frycki8188d762019-04-01 18:03:48 -0700465
466 auto buffer = ipmbResponse.ipmbToi2cConstruct();
467 if (buffer)
468 {
Qiang XUbbfd00a2019-06-27 21:10:06 +0800469 ipmbSendI2cFrame(buffer);
Dawid Frycki8188d762019-04-01 18:03:48 -0700470 }
471
472 return;
473 }
474
475 if (!(netfn & ipmbNetFnResponseMask))
476 {
477 // we are not expecting request here
478 phosphor::logging::log<phosphor::logging::level::ERR>(
479 "processI2cEvent: got a request instead of response");
480 return;
481 }
482
483 // if command is not supported, add it to filter
484 if (cc == ipmbIpmiInvalidCmd)
485 {
486 addFilter(ipmbReqNetFnFromRespNetFn(netfn), cmd);
487 }
488
489 // payload is empty after constructor invocation
490 auto ipmbResponse =
Qiang XUbbfd00a2019-06-27 21:10:06 +0800491 IpmbResponse(address, netfn, rqLun, bmcSlaveAddress, seq,
492 lun, cmd, cc, payload);
Dawid Frycki8188d762019-04-01 18:03:48 -0700493
494 auto buffer = ipmbResponse.ipmbToi2cConstruct();
495 if (!buffer)
496 {
497 phosphor::logging::log<phosphor::logging::level::ERR>(
498 "processI2cEvent: error constructing a request");
499 return;
500 }
501
Qiang XUbbfd00a2019-06-27 21:10:06 +0800502 ipmbSendI2cFrame(buffer);
Dawid Frycki8188d762019-04-01 18:03:48 -0700503 },
504 "xyz.openbmc_project.Ipmi.Host", "/xyz/openbmc_project/Ipmi",
505 "xyz.openbmc_project.Ipmi.Server", "execute",
506 ipmbMessageReceived.netFn, ipmbMessageReceived.rsLun,
507 ipmbMessageReceived.cmd, ipmbMessageReceived.data, options);
Dawid Fryckia642a942018-06-12 10:44:23 -0700508 }
509
510end:
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800511 i2cSlaveDescriptor.async_wait(
512 boost::asio::posix::descriptor_base::wait_read,
Dawid Fryckia642a942018-06-12 10:44:23 -0700513 [this](const boost::system::error_code &ec) {
514 if (ec)
515 {
516 phosphor::logging::log<phosphor::logging::level::ERR>(
517 "Error: processI2cEvent()");
518 return;
519 }
520
521 processI2cEvent();
522 });
523}
524
Ed Tanous1486b8a2023-02-28 13:28:59 -0800525IpmbChannel::IpmbChannel(boost::asio::io_context &io,
Dawid Fryckia642a942018-06-12 10:44:23 -0700526 uint8_t ipmbBmcSlaveAddress,
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530527 uint8_t ipmbRqSlaveAddress, uint8_t channelIdx,
Dawid Fryckia642a942018-06-12 10:44:23 -0700528 std::shared_ptr<IpmbCommandFilter> commandFilter) :
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800529 i2cSlaveDescriptor(io),
530 ipmbBmcSlaveAddress(ipmbBmcSlaveAddress),
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530531 ipmbRqSlaveAddress(ipmbRqSlaveAddress), channelIdx(channelIdx),
Dawid Fryckia642a942018-06-12 10:44:23 -0700532 commandFilter(commandFilter)
533{
534}
535
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800536int IpmbChannel::ipmbChannelInit(const char *ipmbI2cSlave)
Dawid Fryckia642a942018-06-12 10:44:23 -0700537{
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800538 // extract bus id from slave path and save
539 std::string ipmbI2cSlaveStr(ipmbI2cSlave);
540 auto findHyphen = ipmbI2cSlaveStr.find("-");
541 std::string busStr = ipmbI2cSlaveStr.substr(findHyphen + 1);
Qiang XU8edcf1a2019-06-14 22:18:15 +0800542 try
543 {
544 ipmbBusId = std::stoi(busStr);
545 }
Patrick Williamsc0dd70d2021-09-03 08:33:48 -0500546 catch (const std::invalid_argument &)
Qiang XU8edcf1a2019-06-14 22:18:15 +0800547 {
548 phosphor::logging::log<phosphor::logging::level::ERR>(
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800549 "ipmbChannelInit: invalid bus id in slave-path config");
Qiang XU8edcf1a2019-06-14 22:18:15 +0800550 return -1;
551 }
552
553 // Check if sysfs has device. If not, enable I2C slave driver by command
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800554 // echo "ipmb-dev 0x1010" > /sys/bus/i2c/devices/i2c-0/new_device
Qiang XU8edcf1a2019-06-14 22:18:15 +0800555 bool hasSysfs = std::filesystem::exists(ipmbI2cSlave);
556 if (!hasSysfs)
557 {
558 std::string deviceFileName =
559 "/sys/bus/i2c/devices/i2c-" + busStr + "/new_device";
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800560 std::string para = "ipmb-dev 0x1010"; // init with BMC addr 0x20
Qiang XU8edcf1a2019-06-14 22:18:15 +0800561 std::fstream deviceFile;
562 deviceFile.open(deviceFileName, std::ios::out);
563 if (!deviceFile.good())
564 {
565 phosphor::logging::log<phosphor::logging::level::ERR>(
566 "ipmbChannelInit: error opening deviceFile");
567 return -1;
568 }
569 deviceFile << para;
570 deviceFile.close();
571 }
572
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800573 // open fd to i2c slave device for read write
574 ipmbi2cSlaveFd = open(ipmbI2cSlave, O_RDWR | O_NONBLOCK | O_CLOEXEC);
Dawid Fryckia642a942018-06-12 10:44:23 -0700575 if (ipmbi2cSlaveFd < 0)
576 {
577 phosphor::logging::log<phosphor::logging::level::ERR>(
578 "ipmbChannelInit: error opening ipmbI2cSlave");
579 return -1;
580 }
581
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800582 i2cSlaveDescriptor.assign(ipmbi2cSlaveFd);
Dawid Fryckia642a942018-06-12 10:44:23 -0700583
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800584 i2cSlaveDescriptor.async_wait(
585 boost::asio::posix::descriptor_base::wait_read,
Dawid Fryckia642a942018-06-12 10:44:23 -0700586 [this](const boost::system::error_code &ec) {
587 if (ec)
588 {
589 phosphor::logging::log<phosphor::logging::level::ERR>(
590 "Error: processI2cEvent()");
591 return;
592 }
593
594 processI2cEvent();
595 });
596
597 return 0;
598}
599
Qiang XU8edcf1a2019-06-14 22:18:15 +0800600int IpmbChannel::ipmbChannelUpdateSlaveAddress(const uint8_t newBmcSlaveAddr)
601{
602 if (ipmbi2cSlaveFd > 0)
603 {
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800604 i2cSlaveDescriptor.close();
Qiang XU8edcf1a2019-06-14 22:18:15 +0800605 close(ipmbi2cSlaveFd);
606 ipmbi2cSlaveFd = 0;
607 }
608
609 // disable old I2C slave driver by command:
610 // echo "0x1010" > /sys/bus/i2c/devices/i2c-0/delete_device
611 std::string deviceFileName;
612 std::string para;
613 std::fstream deviceFile;
614 deviceFileName = "/sys/bus/i2c/devices/i2c-" + std::to_string(ipmbBusId) +
615 "/delete_device";
616 para = "0x1010"; // align with removed ipmb0 definition in dts file
617 deviceFile.open(deviceFileName, std::ios::out);
618 if (!deviceFile.good())
619 {
620 phosphor::logging::log<phosphor::logging::level::ERR>(
621 "ipmbChannelUpdateSlaveAddress: error opening deviceFile to delete "
622 "sysfs");
623 return -1;
624 }
625 deviceFile << para;
626 deviceFile.close();
627
628 // enable new I2C slave driver by command:
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800629 // echo "ipmb-dev 0x1012" > /sys/bus/i2c/devices/i2c-0/new_device
Qiang XU8edcf1a2019-06-14 22:18:15 +0800630 deviceFileName =
631 "/sys/bus/i2c/devices/i2c-" + std::to_string(ipmbBusId) + "/new_device";
632 std::ostringstream hex;
633 uint16_t addr = 0x1000 + (newBmcSlaveAddr >> 1);
634 hex << std::hex << static_cast<uint16_t>(addr);
635 const std::string &addressHexStr = hex.str();
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800636 para = "ipmb-dev 0x" + addressHexStr;
Qiang XU8edcf1a2019-06-14 22:18:15 +0800637 deviceFile.open(deviceFileName, std::ios::out);
638 if (!deviceFile.good())
639 {
640 phosphor::logging::log<phosphor::logging::level::ERR>(
641 "ipmbChannelUpdateSlaveAddress: error opening deviceFile to create "
642 "sysfs");
643 return -1;
644 }
645 deviceFile << para;
646 deviceFile.close();
647
648 // open fd to i2c slave device
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800649 std::string ipmbI2cSlaveStr = "/dev/ipmb-" + std::to_string(ipmbBusId);
650 ipmbi2cSlaveFd = open(ipmbI2cSlaveStr.c_str(), O_RDWR | O_NONBLOCK);
Qiang XU8edcf1a2019-06-14 22:18:15 +0800651 if (ipmbi2cSlaveFd < 0)
652 {
653 phosphor::logging::log<phosphor::logging::level::ERR>(
654 "ipmbChannelInit: error opening ipmbI2cSlave");
655 return -1;
656 }
657
658 // start to receive i2c data as slave
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800659 i2cSlaveDescriptor.assign(ipmbi2cSlaveFd);
660 i2cSlaveDescriptor.async_wait(
661 boost::asio::posix::descriptor_base::wait_read,
Qiang XU8edcf1a2019-06-14 22:18:15 +0800662 [this](const boost::system::error_code &ec) {
663 if (ec)
664 {
665 phosphor::logging::log<phosphor::logging::level::ERR>(
666 "Error: processI2cEvent()");
667 return;
668 }
669
670 processI2cEvent();
671 });
672
Qiang XUbbfd00a2019-06-27 21:10:06 +0800673 ipmbBmcSlaveAddress = newBmcSlaveAddr;
674
Qiang XU8edcf1a2019-06-14 22:18:15 +0800675 return 0;
676}
677
678uint8_t IpmbChannel::getBusId()
679{
680 return ipmbBusId;
681}
682
Dawid Fryckia642a942018-06-12 10:44:23 -0700683uint8_t IpmbChannel::getBmcSlaveAddress()
684{
685 return ipmbBmcSlaveAddress;
686}
687
688uint8_t IpmbChannel::getRqSlaveAddress()
689{
690 return ipmbRqSlaveAddress;
691}
692
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530693uint8_t IpmbChannel::getDevIndex()
694{
695 return channelIdx >> 2;
696}
697
698uint8_t IpmbChannel::getChannelIdx()
699{
700 return channelIdx;
701}
702
Dawid Fryckia642a942018-06-12 10:44:23 -0700703ipmbChannelType IpmbChannel::getChannelType()
704{
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530705 return static_cast<ipmbChannelType>((channelIdx & 3));
Dawid Fryckia642a942018-06-12 10:44:23 -0700706}
707
708void IpmbChannel::addFilter(const uint8_t respNetFn, const uint8_t cmd)
709{
710 if (commandFilter)
711 {
712 commandFilter->addFilter(respNetFn, cmd);
713 }
714}
715
716std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
717 IpmbChannel::requestAdd(boost::asio::yield_context &yield,
718 std::shared_ptr<IpmbRequest> request)
719{
720 makeRequestValid(request);
721
722 std::vector<uint8_t> buffer(0);
723 if (request->ipmbToi2cConstruct(buffer) != 0)
724 {
725 return returnStatus(ipmbResponseStatus::error);
726 }
727
728 for (int i = 0; i < ipmbNumberOfTries; i++)
729 {
730 boost::system::error_code ec;
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800731 int i2cRetryCnt = 0;
Dawid Fryckia642a942018-06-12 10:44:23 -0700732
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800733 for (; i2cRetryCnt < ipmbI2cNumberOfRetries; i2cRetryCnt++)
Dawid Fryckia642a942018-06-12 10:44:23 -0700734 {
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800735 boost::asio::async_write(i2cSlaveDescriptor,
736 boost::asio::buffer(buffer), yield[ec]);
Dawid Fryckia642a942018-06-12 10:44:23 -0700737
738 if (ec)
739 {
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800740 continue; // retry
Dawid Fryckia642a942018-06-12 10:44:23 -0700741 }
742 break;
743 }
744
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800745 if (i2cRetryCnt == ipmbI2cNumberOfRetries)
746 {
Qiang XUbbfd00a2019-06-27 21:10:06 +0800747 std::string msgToLog =
748 "requestAdd: Sent to I2C failed after retries."
749 " busId=" +
750 std::to_string(ipmbBusId) + ", error=" + ec.message();
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800751 phosphor::logging::log<phosphor::logging::level::INFO>(
Qiang XUbbfd00a2019-06-27 21:10:06 +0800752 msgToLog.c_str());
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800753 }
754
Dawid Fryckia642a942018-06-12 10:44:23 -0700755 request->timer->expires_after(
756 std::chrono::milliseconds(ipmbRequestRetryTimeout));
757 request->timer->async_wait(yield[ec]);
758
759 if (ec && ec != boost::asio::error::operation_aborted)
760 {
761 // unexpected error - invalidate request and return generic error
762 phosphor::logging::log<phosphor::logging::level::ERR>(
763 "requestAdd: async_wait error");
764 makeRequestInvalid(*request);
765 return returnStatus(ipmbResponseStatus::error);
766 }
767
768 if (request->state == ipmbRequestState::matched)
769 {
770 // matched response, send it to client application
771 makeRequestInvalid(*request);
772 return request->returnMatchedResponse();
773 }
774 }
775
776 makeRequestInvalid(*request);
777 return returnStatus(ipmbResponseStatus::timeout);
778}
779
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530780static IpmbChannel *getChannel(uint8_t reqChannel)
Dawid Fryckia642a942018-06-12 10:44:23 -0700781{
782 auto channel =
783 std::find_if(ipmbChannels.begin(), ipmbChannels.end(),
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530784 [reqChannel](IpmbChannel &channel) {
785 return channel.getChannelIdx() == reqChannel;
Dawid Fryckia642a942018-06-12 10:44:23 -0700786 });
787 if (channel != ipmbChannels.end())
788 {
789 return &(*channel);
790 }
791
792 return nullptr;
793}
794
795static int initializeChannels()
796{
797 std::shared_ptr<IpmbCommandFilter> commandFilter =
798 std::make_shared<IpmbCommandFilter>();
799
Amithash Prasad314862d2019-03-26 11:14:03 -0700800 constexpr const char *configFilePath =
801 "/usr/share/ipmbbridge/ipmb-channels.json";
802 std::ifstream configFile(configFilePath);
803 if (!configFile.is_open())
Dawid Fryckia642a942018-06-12 10:44:23 -0700804 {
Amithash Prasad314862d2019-03-26 11:14:03 -0700805 phosphor::logging::log<phosphor::logging::level::ERR>(
806 "initializeChannels: Cannot open config path");
807 return -1;
808 }
809 try
810 {
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530811 uint8_t devIndex = 0;
Amithash Prasad314862d2019-03-26 11:14:03 -0700812 auto data = nlohmann::json::parse(configFile, nullptr);
813 for (const auto &channelConfig : data["channels"])
Dawid Fryckia642a942018-06-12 10:44:23 -0700814 {
Amithash Prasad314862d2019-03-26 11:14:03 -0700815 const std::string &typeConfig = channelConfig["type"];
Amithash Prasad314862d2019-03-26 11:14:03 -0700816 const std::string &slavePath = channelConfig["slave-path"];
817 uint8_t bmcAddr = channelConfig["bmc-addr"];
818 uint8_t reqAddr = channelConfig["remote-addr"];
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530819
Amithash Prasad314862d2019-03-26 11:14:03 -0700820 ipmbChannelType type = ipmbChannelTypeMap.at(typeConfig);
821
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530822 if (channelConfig.contains("devIndex"))
823 {
824 devIndex = channelConfig["devIndex"];
825 }
826
827 auto channel = ipmbChannels.emplace(
828 ipmbChannels.end(), io, bmcAddr, reqAddr,
829 ((devIndex << 2) | static_cast<uint8_t>(type)), commandFilter);
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800830 if (channel->ipmbChannelInit(slavePath.c_str()) < 0)
Amithash Prasad314862d2019-03-26 11:14:03 -0700831 {
832 phosphor::logging::log<phosphor::logging::level::ERR>(
833 "initializeChannels: channel initialization failed");
834 return -1;
835 }
Dawid Fryckia642a942018-06-12 10:44:23 -0700836 }
837 }
Patrick Williamsc0dd70d2021-09-03 08:33:48 -0500838 catch (const nlohmann::json::exception &e)
Amithash Prasad314862d2019-03-26 11:14:03 -0700839 {
840 phosphor::logging::log<phosphor::logging::level::ERR>(
841 "initializeChannels: Error parsing config file");
842 return -1;
843 }
Patrick Williamsc0dd70d2021-09-03 08:33:48 -0500844 catch (const std::out_of_range &e)
Amithash Prasad314862d2019-03-26 11:14:03 -0700845 {
846 phosphor::logging::log<phosphor::logging::level::ERR>(
847 "initializeChannels: Error invalid type");
848 return -1;
849 }
Dawid Fryckia642a942018-06-12 10:44:23 -0700850 return 0;
851}
852
Dawid Fryckia642a942018-06-12 10:44:23 -0700853auto ipmbHandleRequest = [](boost::asio::yield_context yield,
854 uint8_t reqChannel, uint8_t netfn, uint8_t lun,
855 uint8_t cmd, std::vector<uint8_t> dataReceived) {
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530856 IpmbChannel *channel = getChannel(reqChannel);
857
Dawid Fryckia642a942018-06-12 10:44:23 -0700858 if (channel == nullptr)
859 {
860 phosphor::logging::log<phosphor::logging::level::ERR>(
861 "ipmbHandleRequest: requested channel does not exist");
862 return returnStatus(ipmbResponseStatus::invalid_param);
863 }
864
865 // check outstanding request list for valid sequence number
866 uint8_t seqNum = 0;
867 bool seqValid = channel->seqNumGet(seqNum);
868 if (!seqValid)
869 {
870 phosphor::logging::log<phosphor::logging::level::WARNING>(
871 "ipmbHandleRequest: cannot add more requests to the list");
872 return returnStatus(ipmbResponseStatus::busy);
873 }
874
875 uint8_t bmcSlaveAddress = channel->getBmcSlaveAddress();
876 uint8_t rqSlaveAddress = channel->getRqSlaveAddress();
877
878 // construct the request to add it to outstanding request list
879 std::shared_ptr<IpmbRequest> request = std::make_shared<IpmbRequest>(
880 rqSlaveAddress, netfn, ipmbRsLun, bmcSlaveAddress, seqNum, lun, cmd,
881 dataReceived);
882
883 if (!request->timer)
884 {
885 phosphor::logging::log<phosphor::logging::level::ERR>(
886 "ipmbHandleRequest: timer object does not exist");
887 return returnStatus(ipmbResponseStatus::error);
888 }
889
890 return channel->requestAdd(yield, request);
891};
892
Qiang XU8edcf1a2019-06-14 22:18:15 +0800893void addUpdateSlaveAddrHandler()
894{
895 // callback to handle dbus signal of updating slave addr
Patrick Williams3852f8e2022-07-22 19:26:56 -0500896 std::function<void(sdbusplus::message_t &)> updateSlaveAddrHandler =
897 [](sdbusplus::message_t &message) {
Qiang XU8edcf1a2019-06-14 22:18:15 +0800898 uint8_t reqChannel, busId, slaveAddr;
899
900 // valid source of signal, check whether from multi-node manager
901 std::string pathName = message.get_path();
902 if (pathName != "/xyz/openbmc_project/MultiNode/Status")
903 {
904 phosphor::logging::log<phosphor::logging::level::ERR>(
905 "addUpdateSlaveAddrHandler: invalid obj path");
906 return;
907 }
908
909 message.read(reqChannel, busId, slaveAddr);
910
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530911 IpmbChannel *channel = getChannel(reqChannel);
912
Qiang XU8edcf1a2019-06-14 22:18:15 +0800913 if (channel == nullptr ||
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530914 channel->getChannelType() != ipmbChannelType::ipmb)
Qiang XU8edcf1a2019-06-14 22:18:15 +0800915 {
916 phosphor::logging::log<phosphor::logging::level::ERR>(
917 "addUpdateSlaveAddrHandler: invalid channel");
918 return;
919 }
920 if (busId != channel->getBusId())
921 {
922 phosphor::logging::log<phosphor::logging::level::ERR>(
923 "addUpdateSlaveAddrHandler: invalid busId");
924 return;
925 }
926 if (channel->getBmcSlaveAddress() == slaveAddr)
927 {
928 phosphor::logging::log<phosphor::logging::level::INFO>(
929 "addUpdateSlaveAddrHandler: channel bmc slave addr is "
930 "unchanged, do nothing");
931 return;
932 }
933
934 channel->ipmbChannelUpdateSlaveAddress(slaveAddr);
935 };
936
Patrick Williams3852f8e2022-07-22 19:26:56 -0500937 static auto match = std::make_unique<sdbusplus::bus::match_t>(
938 static_cast<sdbusplus::bus_t &>(*conn),
Qiang XU8edcf1a2019-06-14 22:18:15 +0800939 "type='signal',member='updateBmcSlaveAddr',", updateSlaveAddrHandler);
940}
941
Qiang XUbbfd00a2019-06-27 21:10:06 +0800942void addSendBroadcastHandler()
943{
944 // callback to handle dbus signal of sending broadcast message
Patrick Williams3852f8e2022-07-22 19:26:56 -0500945 std::function<void(sdbusplus::message_t &)> sendBroadcastHandler =
946 [](sdbusplus::message_t &message) {
Qiang XUbbfd00a2019-06-27 21:10:06 +0800947 uint8_t reqChannel, netFn, lun, cmd;
948 std::vector<uint8_t> dataReceived;
949 message.read(reqChannel, netFn, lun, cmd, dataReceived);
950
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530951 IpmbChannel *channel = getChannel(reqChannel);
952
Qiang XUbbfd00a2019-06-27 21:10:06 +0800953 if (channel == nullptr)
954 {
955 phosphor::logging::log<phosphor::logging::level::ERR>(
956 "addSendBroadcastMsgHandler: requested channel does not "
957 "exist");
958 return;
959 }
960
961 uint8_t bmcSlaveAddress = channel->getBmcSlaveAddress();
962 uint8_t seqNum = 0; // seqNum is not used in broadcast msg
963 uint8_t targetAddr = broadcastAddress;
964
965 std::shared_ptr<IpmbRequest> request =
966 std::make_shared<IpmbRequest>(targetAddr, netFn, ipmbRsLun,
967 bmcSlaveAddress, seqNum, lun, cmd,
968 dataReceived);
969
970 std::shared_ptr<std::vector<uint8_t>> buffer =
971 std::make_shared<std::vector<uint8_t>>();
972
973 if (request->ipmbToi2cConstruct(*buffer) != 0)
974 {
975 return;
976 }
977
978 channel->ipmbSendI2cFrame(buffer);
979 };
980
Patrick Williams3852f8e2022-07-22 19:26:56 -0500981 static auto match = std::make_unique<sdbusplus::bus::match_t>(
982 static_cast<sdbusplus::bus_t &>(*conn),
Qiang XUbbfd00a2019-06-27 21:10:06 +0800983 "type='signal',member='sendBroadcast',", sendBroadcastHandler);
984}
985
Dawid Fryckia642a942018-06-12 10:44:23 -0700986/**
987 * @brief Main
988 */
989int main(int argc, char *argv[])
990{
991 conn->request_name(ipmbBus);
992
993 auto server = sdbusplus::asio::object_server(conn);
994
Dawid Fryckia642a942018-06-12 10:44:23 -0700995 std::shared_ptr<sdbusplus::asio::dbus_interface> ipmbIface =
996 server.add_interface(ipmbObj, ipmbDbusIntf);
997
Dawid Fryckia642a942018-06-12 10:44:23 -0700998 ipmbIface->register_method("sendRequest", std::move(ipmbHandleRequest));
Dawid Fryckia642a942018-06-12 10:44:23 -0700999 ipmbIface->initialize();
1000
1001 if (initializeChannels() < 0)
1002 {
1003 phosphor::logging::log<phosphor::logging::level::ERR>(
1004 "Error initializeChannels");
1005 return -1;
1006 }
1007
Qiang XU8edcf1a2019-06-14 22:18:15 +08001008 addUpdateSlaveAddrHandler();
1009
Qiang XUbbfd00a2019-06-27 21:10:06 +08001010 addSendBroadcastHandler();
1011
Dawid Fryckia642a942018-06-12 10:44:23 -07001012 io.run();
1013 return 0;
1014}