blob: f8d5142702abc81f7efd0db53d268cb9bf283dbe [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 Tanous09027c02020-08-31 17:28:36 -070022#include <boost/asio/write.hpp>
Qiang XU8edcf1a2019-06-14 22:18:15 +080023#include <filesystem>
Amithash Prasad314862d2019-03-26 11:14:03 -070024#include <fstream>
25#include <nlohmann/json.hpp>
Dawid Fryckia642a942018-06-12 10:44:23 -070026#include <phosphor-logging/log.hpp>
27#include <tuple>
Amithash Prasad314862d2019-03-26 11:14:03 -070028#include <unordered_map>
Dawid Fryckia642a942018-06-12 10:44:23 -070029
Dawid Fryckia642a942018-06-12 10:44:23 -070030/**
31 * @brief Dbus
32 */
33static constexpr const char *ipmbBus = "xyz.openbmc_project.Ipmi.Channel.Ipmb";
34static constexpr const char *ipmbObj = "/xyz/openbmc_project/Ipmi/Channel/Ipmb";
Dawid Fryckia642a942018-06-12 10:44:23 -070035static constexpr const char *ipmbDbusIntf = "org.openbmc.Ipmb";
36
37boost::asio::io_service io;
38auto conn = std::make_shared<sdbusplus::asio::connection>(io);
39
Dawid Fryckia642a942018-06-12 10:44:23 -070040static std::list<IpmbChannel> ipmbChannels;
Amithash Prasad314862d2019-03-26 11:14:03 -070041static const std::unordered_map<std::string, ipmbChannelType>
42 ipmbChannelTypeMap = {{"me", ipmbChannelType::me},
43 {"ipmb", ipmbChannelType::ipmb}};
Dawid Fryckia642a942018-06-12 10:44:23 -070044
45/**
46 * @brief Ipmb request class methods
47 */
48IpmbRequest::IpmbRequest()
49{
50 data.reserve(ipmbMaxDataSize);
51}
52
53IpmbRequest::IpmbRequest(uint8_t address, uint8_t netFn, uint8_t rsLun,
54 uint8_t rqSA, uint8_t seq, uint8_t rqLun, uint8_t cmd,
Dawid Frycki8188d762019-04-01 18:03:48 -070055 const std::vector<uint8_t> &inputData) :
Dawid Fryckia642a942018-06-12 10:44:23 -070056 address(address),
57 netFn(netFn), rsLun(rsLun), rqSA(rqSA), seq(seq), rqLun(rqLun), cmd(cmd),
58 timer(io)
59{
60 data.reserve(ipmbMaxDataSize);
61 state = ipmbRequestState::invalid;
62
63 if (inputData.size() > 0)
64 {
65 data = std::move(inputData);
66 }
67}
68
Dawid Fryckia642a942018-06-12 10:44:23 -070069void IpmbRequest::i2cToIpmbConstruct(IPMB_HEADER *ipmbBuffer,
70 size_t bufferLength)
71{
72 // constructing ipmb request from i2c buffer
73 netFn = ipmbNetFnGet(ipmbBuffer->Header.Req.rsNetFnLUN);
74 rsLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Req.rsNetFnLUN);
75 rqSA = ipmbBuffer->Header.Req.rqSA;
76 seq = ipmbSeqGet(ipmbBuffer->Header.Req.rqSeqLUN);
77 rqLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Req.rqSeqLUN);
78 cmd = ipmbBuffer->Header.Req.cmd;
79
80 size_t dataLength =
81 bufferLength - (ipmbConnectionHeaderLength +
82 ipmbRequestDataHeaderLength + ipmbChecksumSize);
83
84 if (dataLength > 0)
85 {
86 data.insert(data.end(), ipmbBuffer->Header.Req.data,
87 &ipmbBuffer->Header.Req.data[dataLength]);
88 }
89}
90
91int IpmbRequest::ipmbToi2cConstruct(std::vector<uint8_t> &buffer)
92{
Vijay Khemka37a7eac2019-12-06 13:52:28 -080093 /* Add one byte for length byte as per required by driver */
94 size_t bufferLength = 1 + data.size() + ipmbRequestDataHeaderLength +
Dawid Fryckia642a942018-06-12 10:44:23 -070095 ipmbConnectionHeaderLength + ipmbChecksumSize;
96
97 if (bufferLength > ipmbMaxFrameLength)
98 {
99 return -1;
100 }
101
102 buffer.resize(bufferLength);
103 static_assert(ipmbMaxFrameLength >= sizeof(IPMB_HEADER));
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800104 IPMB_PKT *ipmbPkt = reinterpret_cast<IPMB_PKT *>(buffer.data());
105 ipmbPkt->len = bufferLength - 1;
106 IPMB_HEADER *ipmbBuffer = &(ipmbPkt->hdr);
Dawid Fryckia642a942018-06-12 10:44:23 -0700107
108 // constructing buffer from ipmb request
109 ipmbBuffer->Header.Req.address = address;
110 ipmbBuffer->Header.Req.rsNetFnLUN = ipmbNetFnLunSet(netFn, rsLun);
111 ipmbBuffer->Header.Req.rqSA = rqSA;
112 ipmbBuffer->Header.Req.rqSeqLUN = ipmbSeqLunSet(seq, rqLun);
113 ipmbBuffer->Header.Req.cmd = cmd;
114
Qiang XUbbfd00a2019-06-27 21:10:06 +0800115 ipmbBuffer->Header.Req.checksum1 = ipmbChecksumCompute(
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800116 (uint8_t *)ipmbBuffer, ipmbConnectionHeaderLength - ipmbChecksumSize);
Dawid Fryckia642a942018-06-12 10:44:23 -0700117
118 if (data.size() > 0)
119 {
120 std::copy(data.begin(), data.end(), ipmbBuffer->Header.Req.data);
121 }
122
123 buffer[bufferLength - ipmbChecksumSize] =
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800124 ipmbChecksumCompute((uint8_t *)ipmbBuffer + ipmbChecksum2StartOffset,
Dawid Fryckia642a942018-06-12 10:44:23 -0700125 (ipmbRequestDataHeaderLength + data.size()));
126
127 return 0;
128}
129
130std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
131 IpmbRequest::returnMatchedResponse()
132{
133 return std::make_tuple(
134 static_cast<int>(ipmbResponseStatus::success), matchedResponse->netFn,
135 matchedResponse->rsLun, matchedResponse->cmd,
136 matchedResponse->completionCode, matchedResponse->data);
137}
138
139static std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
140 returnStatus(ipmbResponseStatus status)
141{
142 // we only want to send status here, other fields are not relevant
143 return std::make_tuple(static_cast<int>(status), 0, 0, 0, 0,
144 std::vector<uint8_t>(0));
145}
146
Dawid Fryckia642a942018-06-12 10:44:23 -0700147/**
148 * @brief Ipmb response class methods
149 */
150IpmbResponse::IpmbResponse()
151{
152 data.reserve(ipmbMaxDataSize);
153}
154
155IpmbResponse::IpmbResponse(uint8_t address, uint8_t netFn, uint8_t rqLun,
156 uint8_t rsSA, uint8_t seq, uint8_t rsLun,
157 uint8_t cmd, uint8_t completionCode,
Dawid Frycki8188d762019-04-01 18:03:48 -0700158 const std::vector<uint8_t> &inputData) :
Dawid Fryckia642a942018-06-12 10:44:23 -0700159 address(address),
160 netFn(netFn), rqLun(rqLun), rsSA(rsSA), seq(seq), rsLun(rsLun), cmd(cmd),
161 completionCode(completionCode)
162{
163 data.reserve(ipmbMaxDataSize);
164
165 if (inputData.size() > 0)
166 {
167 data = std::move(inputData);
168 }
169}
170
171void IpmbResponse::i2cToIpmbConstruct(IPMB_HEADER *ipmbBuffer,
172 size_t bufferLength)
173{
174 netFn = ipmbNetFnGet(ipmbBuffer->Header.Resp.rqNetFnLUN);
175 rqLun = ipmbLunFromNetFnLunGet(ipmbBuffer->Header.Resp.rqNetFnLUN);
176 rsSA = ipmbBuffer->Header.Resp.rsSA;
177 seq = ipmbSeqGet(ipmbBuffer->Header.Resp.rsSeqLUN);
178 rsLun = ipmbLunFromSeqLunGet(ipmbBuffer->Header.Resp.rsSeqLUN);
179 cmd = ipmbBuffer->Header.Resp.cmd;
180 completionCode = ipmbBuffer->Header.Resp.completionCode;
181
182 size_t dataLength =
183 bufferLength - (ipmbConnectionHeaderLength +
184 ipmbResponseDataHeaderLength + ipmbChecksumSize);
185
186 if (dataLength > 0)
187 {
188 data.insert(data.end(), ipmbBuffer->Header.Resp.data,
189 &ipmbBuffer->Header.Resp.data[dataLength]);
190 }
191}
192
Dawid Frycki8188d762019-04-01 18:03:48 -0700193std::shared_ptr<std::vector<uint8_t>> IpmbResponse::ipmbToi2cConstruct()
Dawid Fryckia642a942018-06-12 10:44:23 -0700194{
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800195 /* Add one byte for length byte as per required by driver */
196 size_t bufferLength = 1 + data.size() + ipmbResponseDataHeaderLength +
Dawid Fryckia642a942018-06-12 10:44:23 -0700197 ipmbConnectionHeaderLength + ipmbChecksumSize;
198
199 if (bufferLength > ipmbMaxFrameLength)
200 {
Dawid Frycki8188d762019-04-01 18:03:48 -0700201 return nullptr;
Dawid Fryckia642a942018-06-12 10:44:23 -0700202 }
203
Dawid Frycki8188d762019-04-01 18:03:48 -0700204 std::shared_ptr<std::vector<uint8_t>> buffer =
205 std::make_shared<std::vector<uint8_t>>(bufferLength);
206
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800207 IPMB_PKT *ipmbPkt = reinterpret_cast<IPMB_PKT *>(buffer->data());
208 ipmbPkt->len = bufferLength - 1;
209 IPMB_HEADER *ipmbBuffer = &(ipmbPkt->hdr);
Dawid Fryckia642a942018-06-12 10:44:23 -0700210
211 ipmbBuffer->Header.Resp.address = address;
212 ipmbBuffer->Header.Resp.rqNetFnLUN = ipmbNetFnLunSet(netFn, rqLun);
213 ipmbBuffer->Header.Resp.rsSA = rsSA;
214 ipmbBuffer->Header.Resp.rsSeqLUN = ipmbSeqLunSet(seq, rsLun);
215 ipmbBuffer->Header.Resp.cmd = cmd;
216 ipmbBuffer->Header.Resp.completionCode = completionCode;
217
218 ipmbBuffer->Header.Resp.checksum1 = ipmbChecksumCompute(
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800219 (uint8_t *)ipmbBuffer, ipmbConnectionHeaderLength - ipmbChecksumSize);
Dawid Fryckia642a942018-06-12 10:44:23 -0700220
221 if (data.size() > 0)
222 {
223 std::copy(data.begin(), data.end(), ipmbBuffer->Header.Resp.data);
224 }
225
Dawid Frycki8188d762019-04-01 18:03:48 -0700226 (*buffer)[bufferLength - ipmbChecksumSize] =
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800227 ipmbChecksumCompute((uint8_t *)ipmbBuffer + ipmbChecksum2StartOffset,
Dawid Fryckia642a942018-06-12 10:44:23 -0700228 (ipmbResponseDataHeaderLength + data.size()));
229
Dawid Frycki8188d762019-04-01 18:03:48 -0700230 return buffer;
Dawid Fryckia642a942018-06-12 10:44:23 -0700231}
232
233bool IpmbCommandFilter::isBlocked(const uint8_t reqNetFn, const uint8_t cmd)
234{
235 auto blockedCmd = unhandledCommands.find({reqNetFn, cmd});
236
237 if (blockedCmd != unhandledCommands.end())
238 {
239 return true;
240 }
241
242 return false;
243}
244
245void IpmbCommandFilter::addFilter(const uint8_t reqNetFn, const uint8_t cmd)
246{
247 if (unhandledCommands.insert({reqNetFn, cmd}).second)
248 {
249 phosphor::logging::log<phosphor::logging::level::INFO>(
250 "addFilter: added command to filter",
251 phosphor::logging::entry("netFn = %d", reqNetFn),
252 phosphor::logging::entry("cmd = %d", cmd));
253 }
254}
255
256/**
257 * @brief Ipmb channel
258 */
Qiang XUbbfd00a2019-06-27 21:10:06 +0800259void IpmbChannel::ipmbSendI2cFrame(std::shared_ptr<std::vector<uint8_t>> buffer,
Dawid Fryckia642a942018-06-12 10:44:23 -0700260 size_t retriesAttempted = 0)
261{
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800262 IPMB_PKT *ipmbPkt = reinterpret_cast<IPMB_PKT *>(buffer->data());
263 uint8_t targetAddr = ipmbIsResponse(&(ipmbPkt->hdr))
264 ? ipmbPkt->hdr.Header.Resp.address
265 : ipmbPkt->hdr.Header.Req.address;
266 boost::asio::async_write(
267 i2cSlaveDescriptor, boost::asio::buffer(*buffer),
268 [this, buffer, retriesAttempted,
269 targetAddr](const boost::system::error_code &ec, size_t bytesSent) {
270 if (ec)
Dawid Fryckia642a942018-06-12 10:44:23 -0700271 {
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800272 size_t currentRetryCnt = retriesAttempted;
273
274 if (currentRetryCnt > ipmbI2cNumberOfRetries)
275 {
276 std::string msgToLog =
277 "ipmbSendI2cFrame: send to I2C failed after retries."
278 " busId=" +
279 std::to_string(ipmbBusId) +
280 ", targetAddr=" + std::to_string(targetAddr) +
281 ", error=" + ec.message();
282 phosphor::logging::log<phosphor::logging::level::ERR>(
283 msgToLog.c_str());
284 return;
285 }
286 currentRetryCnt++;
287 ipmbSendI2cFrame(buffer, currentRetryCnt);
Dawid Fryckia642a942018-06-12 10:44:23 -0700288 }
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800289 });
Dawid Fryckia642a942018-06-12 10:44:23 -0700290}
291
292/**
293 * @brief Ipmb Outstanding Requests
294 */
295void IpmbChannel::makeRequestInvalid(IpmbRequest &request)
296{
297 // change request state to invalid and remove it from outstanding requests
298 // list
299 request.state = ipmbRequestState::invalid;
300 outstandingRequests[request.seq] = nullptr;
301}
302
303void IpmbChannel::makeRequestValid(std::shared_ptr<IpmbRequest> request)
304{
305 // change request state to valid and add it to outstanding requests list
306 request->state = ipmbRequestState::valid;
307 outstandingRequests[request->seq] = request;
308}
309
310bool IpmbChannel::seqNumGet(uint8_t &seq)
311{
312 static uint8_t seqNum = 0;
313
314 for (int i = 0; i < ipmbMaxOutstandingRequestsCount; i++)
315 {
316 seqNum = ++seqNum & ipmbSeqMask;
317 if (seqNum == ipmbMaxOutstandingRequestsCount)
318 {
319 seqNum = 0;
320 }
321
322 if (outstandingRequests[seqNum] == nullptr)
323 {
324 seq = seqNum;
325 return true;
326 }
327 }
328
329 return false;
330}
331
332void IpmbChannel::responseMatch(std::unique_ptr<IpmbResponse> &response)
333{
334 std::shared_ptr<IpmbRequest> request = outstandingRequests[response->seq];
335
336 if (request != nullptr)
337 {
338 if (((ipmbRespNetFn(request->netFn)) == (response->netFn)) &&
339 ((request->rqLun) == (response->rqLun)) &&
340 ((request->rsLun) == (response->rsLun)) &&
341 ((request->cmd) == (response->cmd)))
342 {
343 // match, response is corresponding to previously sent request
344 request->state = ipmbRequestState::matched;
345 request->timer->cancel();
346 request->matchedResponse = std::move(response);
347 }
348 }
349}
350
351void IpmbChannel::processI2cEvent()
352{
353 std::array<uint8_t, ipmbMaxFrameLength> buffer{};
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800354 IPMB_PKT *ipmbPkt = reinterpret_cast<IPMB_PKT *>(buffer.data());
355 IPMB_HEADER *ipmbFrame = &(ipmbPkt->hdr);
Dawid Fryckia642a942018-06-12 10:44:23 -0700356
357 lseek(ipmbi2cSlaveFd, 0, SEEK_SET);
358 int r = read(ipmbi2cSlaveFd, buffer.data(), ipmbMaxFrameLength);
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800359
360 /* Substract first byte len size from total frame length */
361 r--;
362
Dawid Fryckia642a942018-06-12 10:44:23 -0700363 if ((r < ipmbMinFrameLength) || (r > ipmbMaxFrameLength))
364 {
365 goto end;
366 }
367
368 // valiate the frame
369 if (!isFrameValid(ipmbFrame, r))
370 {
371 goto end;
372 }
373
Chen Yugang15185ff2020-09-01 09:20:33 +0800374 // if it is message received from ipmb channel, send out dbus signal
375 if (getChannelType() == ipmbChannelType::ipmb)
Qiang XUbbfd00a2019-06-27 21:10:06 +0800376 {
377 auto ipmbMessageReceived = IpmbRequest();
378 ipmbMessageReceived.i2cToIpmbConstruct(ipmbFrame, r);
379 sdbusplus::message::message msg =
380 conn->new_signal(ipmbObj, ipmbDbusIntf, "receiveBroadcast");
381 msg.append(ipmbMessageReceived.netFn, ipmbMessageReceived.cmd,
382 ipmbMessageReceived.data);
383 msg.signal_send();
384 }
385
Dawid Fryckia642a942018-06-12 10:44:23 -0700386 // copy frame to ipmib message buffer
Chen Yugang3e07b9e2020-10-13 16:14:04 +0800387 if (ipmbIsResponse(ipmbFrame))
Dawid Fryckia642a942018-06-12 10:44:23 -0700388 {
389 std::unique_ptr<IpmbResponse> ipmbMessageReceived =
390 std::make_unique<IpmbResponse>();
391
392 ipmbMessageReceived->i2cToIpmbConstruct(ipmbFrame, r);
393
394 // try to match response with outstanding request
395 responseMatch(ipmbMessageReceived);
396 }
397 else
398 {
399 // if command is blocked - respond with 'invalid command'
400 // completion code
401 if (commandFilter)
402 {
403 uint8_t netFn = ipmbNetFnGet(ipmbFrame->Header.Req.rsNetFnLUN);
404 uint8_t cmd = ipmbFrame->Header.Req.cmd;
Qiang XUbbfd00a2019-06-27 21:10:06 +0800405 uint8_t rqSA = ipmbFrame->Header.Req.rqSA;
Dawid Fryckia642a942018-06-12 10:44:23 -0700406
407 if (commandFilter->isBlocked(netFn, cmd))
408 {
409 uint8_t seq = ipmbSeqGet(ipmbFrame->Header.Req.rqSeqLUN);
410 uint8_t lun =
411 ipmbLunFromSeqLunGet(ipmbFrame->Header.Req.rqSeqLUN);
Dawid Fryckia642a942018-06-12 10:44:23 -0700412
413 // prepare generic response
Qiang XUbbfd00a2019-06-27 21:10:06 +0800414 auto ipmbResponse = IpmbResponse(
415 rqSA, ipmbRespNetFn(netFn), lun, ipmbBmcSlaveAddress, seq,
416 ipmbRsLun, cmd, ipmbIpmiInvalidCmd, {});
Dawid Fryckia642a942018-06-12 10:44:23 -0700417
Dawid Frycki8188d762019-04-01 18:03:48 -0700418 auto buffer = ipmbResponse.ipmbToi2cConstruct();
419 if (buffer)
Dawid Fryckia642a942018-06-12 10:44:23 -0700420 {
Qiang XUbbfd00a2019-06-27 21:10:06 +0800421 ipmbSendI2cFrame(buffer);
Dawid Fryckia642a942018-06-12 10:44:23 -0700422 }
423
424 goto end;
425 }
426 }
427
428 auto ipmbMessageReceived = IpmbRequest();
Dawid Fryckia642a942018-06-12 10:44:23 -0700429 ipmbMessageReceived.i2cToIpmbConstruct(ipmbFrame, r);
430
Kumar Thangavel8fe0abe2020-08-19 21:42:23 +0530431 int devId = getDevIndex();
432
Dawid Frycki8188d762019-04-01 18:03:48 -0700433 std::map<std::string, std::variant<int>> options{
Kumar Thangavel8fe0abe2020-08-19 21:42:23 +0530434 {"rqSA", ipmbAddressTo7BitSet(ipmbMessageReceived.rqSA)},
435 {"hostId", devId}};
436
Dawid Frycki8188d762019-04-01 18:03:48 -0700437 using IpmiDbusRspType = std::tuple<uint8_t, uint8_t, uint8_t, uint8_t,
438 std::vector<uint8_t>>;
439 conn->async_method_call(
440 [this, rqLun{ipmbMessageReceived.rqLun},
Qiang XUbbfd00a2019-06-27 21:10:06 +0800441 seq{ipmbMessageReceived.seq}, address{ipmbMessageReceived.rqSA}](
442 const boost::system::error_code &ec,
443 const IpmiDbusRspType &response) {
Dawid Frycki8188d762019-04-01 18:03:48 -0700444 const auto &[netfn, lun, cmd, cc, payload] = response;
445 if (ec)
446 {
447 phosphor::logging::log<phosphor::logging::level::ERR>(
448 "processI2cEvent: error getting response from IPMI");
449 return;
450 }
Dawid Fryckia642a942018-06-12 10:44:23 -0700451
Dawid Frycki8188d762019-04-01 18:03:48 -0700452 uint8_t bmcSlaveAddress = getBmcSlaveAddress();
453
454 if (payload.size() > ipmbMaxDataSize)
455 {
456 phosphor::logging::log<phosphor::logging::level::ERR>(
457 "processI2cEvent: response exceeding maximum size");
458
459 // prepare generic response
460 auto ipmbResponse = IpmbResponse(
Qiang XUbbfd00a2019-06-27 21:10:06 +0800461 address, netfn, rqLun, bmcSlaveAddress, seq, ipmbRsLun,
462 cmd, ipmbIpmiCmdRespNotProvided, {});
Dawid Frycki8188d762019-04-01 18:03:48 -0700463
464 auto buffer = ipmbResponse.ipmbToi2cConstruct();
465 if (buffer)
466 {
Qiang XUbbfd00a2019-06-27 21:10:06 +0800467 ipmbSendI2cFrame(buffer);
Dawid Frycki8188d762019-04-01 18:03:48 -0700468 }
469
470 return;
471 }
472
473 if (!(netfn & ipmbNetFnResponseMask))
474 {
475 // we are not expecting request here
476 phosphor::logging::log<phosphor::logging::level::ERR>(
477 "processI2cEvent: got a request instead of response");
478 return;
479 }
480
481 // if command is not supported, add it to filter
482 if (cc == ipmbIpmiInvalidCmd)
483 {
484 addFilter(ipmbReqNetFnFromRespNetFn(netfn), cmd);
485 }
486
487 // payload is empty after constructor invocation
488 auto ipmbResponse =
Qiang XUbbfd00a2019-06-27 21:10:06 +0800489 IpmbResponse(address, netfn, rqLun, bmcSlaveAddress, seq,
490 lun, cmd, cc, payload);
Dawid Frycki8188d762019-04-01 18:03:48 -0700491
492 auto buffer = ipmbResponse.ipmbToi2cConstruct();
493 if (!buffer)
494 {
495 phosphor::logging::log<phosphor::logging::level::ERR>(
496 "processI2cEvent: error constructing a request");
497 return;
498 }
499
Qiang XUbbfd00a2019-06-27 21:10:06 +0800500 ipmbSendI2cFrame(buffer);
Dawid Frycki8188d762019-04-01 18:03:48 -0700501 },
502 "xyz.openbmc_project.Ipmi.Host", "/xyz/openbmc_project/Ipmi",
503 "xyz.openbmc_project.Ipmi.Server", "execute",
504 ipmbMessageReceived.netFn, ipmbMessageReceived.rsLun,
505 ipmbMessageReceived.cmd, ipmbMessageReceived.data, options);
Dawid Fryckia642a942018-06-12 10:44:23 -0700506 }
507
508end:
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800509 i2cSlaveDescriptor.async_wait(
510 boost::asio::posix::descriptor_base::wait_read,
Dawid Fryckia642a942018-06-12 10:44:23 -0700511 [this](const boost::system::error_code &ec) {
512 if (ec)
513 {
514 phosphor::logging::log<phosphor::logging::level::ERR>(
515 "Error: processI2cEvent()");
516 return;
517 }
518
519 processI2cEvent();
520 });
521}
522
523IpmbChannel::IpmbChannel(boost::asio::io_service &io,
524 uint8_t ipmbBmcSlaveAddress,
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530525 uint8_t ipmbRqSlaveAddress, uint8_t channelIdx,
Dawid Fryckia642a942018-06-12 10:44:23 -0700526 std::shared_ptr<IpmbCommandFilter> commandFilter) :
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800527 i2cSlaveDescriptor(io),
528 ipmbBmcSlaveAddress(ipmbBmcSlaveAddress),
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530529 ipmbRqSlaveAddress(ipmbRqSlaveAddress), channelIdx(channelIdx),
Dawid Fryckia642a942018-06-12 10:44:23 -0700530 commandFilter(commandFilter)
531{
532}
533
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800534int IpmbChannel::ipmbChannelInit(const char *ipmbI2cSlave)
Dawid Fryckia642a942018-06-12 10:44:23 -0700535{
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800536 // extract bus id from slave path and save
537 std::string ipmbI2cSlaveStr(ipmbI2cSlave);
538 auto findHyphen = ipmbI2cSlaveStr.find("-");
539 std::string busStr = ipmbI2cSlaveStr.substr(findHyphen + 1);
Qiang XU8edcf1a2019-06-14 22:18:15 +0800540 try
541 {
542 ipmbBusId = std::stoi(busStr);
543 }
Patrick Williamsc0dd70d2021-09-03 08:33:48 -0500544 catch (const std::invalid_argument &)
Qiang XU8edcf1a2019-06-14 22:18:15 +0800545 {
546 phosphor::logging::log<phosphor::logging::level::ERR>(
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800547 "ipmbChannelInit: invalid bus id in slave-path config");
Qiang XU8edcf1a2019-06-14 22:18:15 +0800548 return -1;
549 }
550
551 // Check if sysfs has device. If not, enable I2C slave driver by command
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800552 // echo "ipmb-dev 0x1010" > /sys/bus/i2c/devices/i2c-0/new_device
Qiang XU8edcf1a2019-06-14 22:18:15 +0800553 bool hasSysfs = std::filesystem::exists(ipmbI2cSlave);
554 if (!hasSysfs)
555 {
556 std::string deviceFileName =
557 "/sys/bus/i2c/devices/i2c-" + busStr + "/new_device";
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800558 std::string para = "ipmb-dev 0x1010"; // init with BMC addr 0x20
Qiang XU8edcf1a2019-06-14 22:18:15 +0800559 std::fstream deviceFile;
560 deviceFile.open(deviceFileName, std::ios::out);
561 if (!deviceFile.good())
562 {
563 phosphor::logging::log<phosphor::logging::level::ERR>(
564 "ipmbChannelInit: error opening deviceFile");
565 return -1;
566 }
567 deviceFile << para;
568 deviceFile.close();
569 }
570
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800571 // open fd to i2c slave device for read write
572 ipmbi2cSlaveFd = open(ipmbI2cSlave, O_RDWR | O_NONBLOCK | O_CLOEXEC);
Dawid Fryckia642a942018-06-12 10:44:23 -0700573 if (ipmbi2cSlaveFd < 0)
574 {
575 phosphor::logging::log<phosphor::logging::level::ERR>(
576 "ipmbChannelInit: error opening ipmbI2cSlave");
577 return -1;
578 }
579
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800580 i2cSlaveDescriptor.assign(ipmbi2cSlaveFd);
Dawid Fryckia642a942018-06-12 10:44:23 -0700581
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800582 i2cSlaveDescriptor.async_wait(
583 boost::asio::posix::descriptor_base::wait_read,
Dawid Fryckia642a942018-06-12 10:44:23 -0700584 [this](const boost::system::error_code &ec) {
585 if (ec)
586 {
587 phosphor::logging::log<phosphor::logging::level::ERR>(
588 "Error: processI2cEvent()");
589 return;
590 }
591
592 processI2cEvent();
593 });
594
595 return 0;
596}
597
Qiang XU8edcf1a2019-06-14 22:18:15 +0800598int IpmbChannel::ipmbChannelUpdateSlaveAddress(const uint8_t newBmcSlaveAddr)
599{
600 if (ipmbi2cSlaveFd > 0)
601 {
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800602 i2cSlaveDescriptor.close();
Qiang XU8edcf1a2019-06-14 22:18:15 +0800603 close(ipmbi2cSlaveFd);
604 ipmbi2cSlaveFd = 0;
605 }
606
607 // disable old I2C slave driver by command:
608 // echo "0x1010" > /sys/bus/i2c/devices/i2c-0/delete_device
609 std::string deviceFileName;
610 std::string para;
611 std::fstream deviceFile;
612 deviceFileName = "/sys/bus/i2c/devices/i2c-" + std::to_string(ipmbBusId) +
613 "/delete_device";
614 para = "0x1010"; // align with removed ipmb0 definition in dts file
615 deviceFile.open(deviceFileName, std::ios::out);
616 if (!deviceFile.good())
617 {
618 phosphor::logging::log<phosphor::logging::level::ERR>(
619 "ipmbChannelUpdateSlaveAddress: error opening deviceFile to delete "
620 "sysfs");
621 return -1;
622 }
623 deviceFile << para;
624 deviceFile.close();
625
626 // enable new I2C slave driver by command:
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800627 // echo "ipmb-dev 0x1012" > /sys/bus/i2c/devices/i2c-0/new_device
Qiang XU8edcf1a2019-06-14 22:18:15 +0800628 deviceFileName =
629 "/sys/bus/i2c/devices/i2c-" + std::to_string(ipmbBusId) + "/new_device";
630 std::ostringstream hex;
631 uint16_t addr = 0x1000 + (newBmcSlaveAddr >> 1);
632 hex << std::hex << static_cast<uint16_t>(addr);
633 const std::string &addressHexStr = hex.str();
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800634 para = "ipmb-dev 0x" + addressHexStr;
Qiang XU8edcf1a2019-06-14 22:18:15 +0800635 deviceFile.open(deviceFileName, std::ios::out);
636 if (!deviceFile.good())
637 {
638 phosphor::logging::log<phosphor::logging::level::ERR>(
639 "ipmbChannelUpdateSlaveAddress: error opening deviceFile to create "
640 "sysfs");
641 return -1;
642 }
643 deviceFile << para;
644 deviceFile.close();
645
646 // open fd to i2c slave device
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800647 std::string ipmbI2cSlaveStr = "/dev/ipmb-" + std::to_string(ipmbBusId);
648 ipmbi2cSlaveFd = open(ipmbI2cSlaveStr.c_str(), O_RDWR | O_NONBLOCK);
Qiang XU8edcf1a2019-06-14 22:18:15 +0800649 if (ipmbi2cSlaveFd < 0)
650 {
651 phosphor::logging::log<phosphor::logging::level::ERR>(
652 "ipmbChannelInit: error opening ipmbI2cSlave");
653 return -1;
654 }
655
656 // start to receive i2c data as slave
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800657 i2cSlaveDescriptor.assign(ipmbi2cSlaveFd);
658 i2cSlaveDescriptor.async_wait(
659 boost::asio::posix::descriptor_base::wait_read,
Qiang XU8edcf1a2019-06-14 22:18:15 +0800660 [this](const boost::system::error_code &ec) {
661 if (ec)
662 {
663 phosphor::logging::log<phosphor::logging::level::ERR>(
664 "Error: processI2cEvent()");
665 return;
666 }
667
668 processI2cEvent();
669 });
670
Qiang XUbbfd00a2019-06-27 21:10:06 +0800671 ipmbBmcSlaveAddress = newBmcSlaveAddr;
672
Qiang XU8edcf1a2019-06-14 22:18:15 +0800673 return 0;
674}
675
676uint8_t IpmbChannel::getBusId()
677{
678 return ipmbBusId;
679}
680
Dawid Fryckia642a942018-06-12 10:44:23 -0700681uint8_t IpmbChannel::getBmcSlaveAddress()
682{
683 return ipmbBmcSlaveAddress;
684}
685
686uint8_t IpmbChannel::getRqSlaveAddress()
687{
688 return ipmbRqSlaveAddress;
689}
690
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530691uint8_t IpmbChannel::getDevIndex()
692{
693 return channelIdx >> 2;
694}
695
696uint8_t IpmbChannel::getChannelIdx()
697{
698 return channelIdx;
699}
700
Dawid Fryckia642a942018-06-12 10:44:23 -0700701ipmbChannelType IpmbChannel::getChannelType()
702{
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530703 return static_cast<ipmbChannelType>((channelIdx & 3));
Dawid Fryckia642a942018-06-12 10:44:23 -0700704}
705
706void IpmbChannel::addFilter(const uint8_t respNetFn, const uint8_t cmd)
707{
708 if (commandFilter)
709 {
710 commandFilter->addFilter(respNetFn, cmd);
711 }
712}
713
714std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>
715 IpmbChannel::requestAdd(boost::asio::yield_context &yield,
716 std::shared_ptr<IpmbRequest> request)
717{
718 makeRequestValid(request);
719
720 std::vector<uint8_t> buffer(0);
721 if (request->ipmbToi2cConstruct(buffer) != 0)
722 {
723 return returnStatus(ipmbResponseStatus::error);
724 }
725
726 for (int i = 0; i < ipmbNumberOfTries; i++)
727 {
728 boost::system::error_code ec;
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800729 int i2cRetryCnt = 0;
Dawid Fryckia642a942018-06-12 10:44:23 -0700730
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800731 for (; i2cRetryCnt < ipmbI2cNumberOfRetries; i2cRetryCnt++)
Dawid Fryckia642a942018-06-12 10:44:23 -0700732 {
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800733 boost::asio::async_write(i2cSlaveDescriptor,
734 boost::asio::buffer(buffer), yield[ec]);
Dawid Fryckia642a942018-06-12 10:44:23 -0700735
736 if (ec)
737 {
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800738 continue; // retry
Dawid Fryckia642a942018-06-12 10:44:23 -0700739 }
740 break;
741 }
742
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800743 if (i2cRetryCnt == ipmbI2cNumberOfRetries)
744 {
Qiang XUbbfd00a2019-06-27 21:10:06 +0800745 std::string msgToLog =
746 "requestAdd: Sent to I2C failed after retries."
747 " busId=" +
748 std::to_string(ipmbBusId) + ", error=" + ec.message();
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800749 phosphor::logging::log<phosphor::logging::level::INFO>(
Qiang XUbbfd00a2019-06-27 21:10:06 +0800750 msgToLog.c_str());
Jae Hyun Yoo25e85c72019-03-05 14:28:13 -0800751 }
752
Dawid Fryckia642a942018-06-12 10:44:23 -0700753 request->timer->expires_after(
754 std::chrono::milliseconds(ipmbRequestRetryTimeout));
755 request->timer->async_wait(yield[ec]);
756
757 if (ec && ec != boost::asio::error::operation_aborted)
758 {
759 // unexpected error - invalidate request and return generic error
760 phosphor::logging::log<phosphor::logging::level::ERR>(
761 "requestAdd: async_wait error");
762 makeRequestInvalid(*request);
763 return returnStatus(ipmbResponseStatus::error);
764 }
765
766 if (request->state == ipmbRequestState::matched)
767 {
768 // matched response, send it to client application
769 makeRequestInvalid(*request);
770 return request->returnMatchedResponse();
771 }
772 }
773
774 makeRequestInvalid(*request);
775 return returnStatus(ipmbResponseStatus::timeout);
776}
777
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530778static IpmbChannel *getChannel(uint8_t reqChannel)
Dawid Fryckia642a942018-06-12 10:44:23 -0700779{
780 auto channel =
781 std::find_if(ipmbChannels.begin(), ipmbChannels.end(),
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530782 [reqChannel](IpmbChannel &channel) {
783 return channel.getChannelIdx() == reqChannel;
Dawid Fryckia642a942018-06-12 10:44:23 -0700784 });
785 if (channel != ipmbChannels.end())
786 {
787 return &(*channel);
788 }
789
790 return nullptr;
791}
792
793static int initializeChannels()
794{
795 std::shared_ptr<IpmbCommandFilter> commandFilter =
796 std::make_shared<IpmbCommandFilter>();
797
Amithash Prasad314862d2019-03-26 11:14:03 -0700798 constexpr const char *configFilePath =
799 "/usr/share/ipmbbridge/ipmb-channels.json";
800 std::ifstream configFile(configFilePath);
801 if (!configFile.is_open())
Dawid Fryckia642a942018-06-12 10:44:23 -0700802 {
Amithash Prasad314862d2019-03-26 11:14:03 -0700803 phosphor::logging::log<phosphor::logging::level::ERR>(
804 "initializeChannels: Cannot open config path");
805 return -1;
806 }
807 try
808 {
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530809 uint8_t devIndex = 0;
Amithash Prasad314862d2019-03-26 11:14:03 -0700810 auto data = nlohmann::json::parse(configFile, nullptr);
811 for (const auto &channelConfig : data["channels"])
Dawid Fryckia642a942018-06-12 10:44:23 -0700812 {
Amithash Prasad314862d2019-03-26 11:14:03 -0700813 const std::string &typeConfig = channelConfig["type"];
Amithash Prasad314862d2019-03-26 11:14:03 -0700814 const std::string &slavePath = channelConfig["slave-path"];
815 uint8_t bmcAddr = channelConfig["bmc-addr"];
816 uint8_t reqAddr = channelConfig["remote-addr"];
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530817
Amithash Prasad314862d2019-03-26 11:14:03 -0700818 ipmbChannelType type = ipmbChannelTypeMap.at(typeConfig);
819
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530820 if (channelConfig.contains("devIndex"))
821 {
822 devIndex = channelConfig["devIndex"];
823 }
824
825 auto channel = ipmbChannels.emplace(
826 ipmbChannels.end(), io, bmcAddr, reqAddr,
827 ((devIndex << 2) | static_cast<uint8_t>(type)), commandFilter);
Vijay Khemka37a7eac2019-12-06 13:52:28 -0800828 if (channel->ipmbChannelInit(slavePath.c_str()) < 0)
Amithash Prasad314862d2019-03-26 11:14:03 -0700829 {
830 phosphor::logging::log<phosphor::logging::level::ERR>(
831 "initializeChannels: channel initialization failed");
832 return -1;
833 }
Dawid Fryckia642a942018-06-12 10:44:23 -0700834 }
835 }
Patrick Williamsc0dd70d2021-09-03 08:33:48 -0500836 catch (const nlohmann::json::exception &e)
Amithash Prasad314862d2019-03-26 11:14:03 -0700837 {
838 phosphor::logging::log<phosphor::logging::level::ERR>(
839 "initializeChannels: Error parsing config file");
840 return -1;
841 }
Patrick Williamsc0dd70d2021-09-03 08:33:48 -0500842 catch (const std::out_of_range &e)
Amithash Prasad314862d2019-03-26 11:14:03 -0700843 {
844 phosphor::logging::log<phosphor::logging::level::ERR>(
845 "initializeChannels: Error invalid type");
846 return -1;
847 }
Dawid Fryckia642a942018-06-12 10:44:23 -0700848 return 0;
849}
850
Dawid Fryckia642a942018-06-12 10:44:23 -0700851auto ipmbHandleRequest = [](boost::asio::yield_context yield,
852 uint8_t reqChannel, uint8_t netfn, uint8_t lun,
853 uint8_t cmd, std::vector<uint8_t> dataReceived) {
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530854 IpmbChannel *channel = getChannel(reqChannel);
855
Dawid Fryckia642a942018-06-12 10:44:23 -0700856 if (channel == nullptr)
857 {
858 phosphor::logging::log<phosphor::logging::level::ERR>(
859 "ipmbHandleRequest: requested channel does not exist");
860 return returnStatus(ipmbResponseStatus::invalid_param);
861 }
862
863 // check outstanding request list for valid sequence number
864 uint8_t seqNum = 0;
865 bool seqValid = channel->seqNumGet(seqNum);
866 if (!seqValid)
867 {
868 phosphor::logging::log<phosphor::logging::level::WARNING>(
869 "ipmbHandleRequest: cannot add more requests to the list");
870 return returnStatus(ipmbResponseStatus::busy);
871 }
872
873 uint8_t bmcSlaveAddress = channel->getBmcSlaveAddress();
874 uint8_t rqSlaveAddress = channel->getRqSlaveAddress();
875
876 // construct the request to add it to outstanding request list
877 std::shared_ptr<IpmbRequest> request = std::make_shared<IpmbRequest>(
878 rqSlaveAddress, netfn, ipmbRsLun, bmcSlaveAddress, seqNum, lun, cmd,
879 dataReceived);
880
881 if (!request->timer)
882 {
883 phosphor::logging::log<phosphor::logging::level::ERR>(
884 "ipmbHandleRequest: timer object does not exist");
885 return returnStatus(ipmbResponseStatus::error);
886 }
887
888 return channel->requestAdd(yield, request);
889};
890
Qiang XU8edcf1a2019-06-14 22:18:15 +0800891void addUpdateSlaveAddrHandler()
892{
893 // callback to handle dbus signal of updating slave addr
894 std::function<void(sdbusplus::message::message &)> updateSlaveAddrHandler =
895 [](sdbusplus::message::message &message) {
896 uint8_t reqChannel, busId, slaveAddr;
897
898 // valid source of signal, check whether from multi-node manager
899 std::string pathName = message.get_path();
900 if (pathName != "/xyz/openbmc_project/MultiNode/Status")
901 {
902 phosphor::logging::log<phosphor::logging::level::ERR>(
903 "addUpdateSlaveAddrHandler: invalid obj path");
904 return;
905 }
906
907 message.read(reqChannel, busId, slaveAddr);
908
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530909 IpmbChannel *channel = getChannel(reqChannel);
910
Qiang XU8edcf1a2019-06-14 22:18:15 +0800911 if (channel == nullptr ||
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530912 channel->getChannelType() != ipmbChannelType::ipmb)
Qiang XU8edcf1a2019-06-14 22:18:15 +0800913 {
914 phosphor::logging::log<phosphor::logging::level::ERR>(
915 "addUpdateSlaveAddrHandler: invalid channel");
916 return;
917 }
918 if (busId != channel->getBusId())
919 {
920 phosphor::logging::log<phosphor::logging::level::ERR>(
921 "addUpdateSlaveAddrHandler: invalid busId");
922 return;
923 }
924 if (channel->getBmcSlaveAddress() == slaveAddr)
925 {
926 phosphor::logging::log<phosphor::logging::level::INFO>(
927 "addUpdateSlaveAddrHandler: channel bmc slave addr is "
928 "unchanged, do nothing");
929 return;
930 }
931
932 channel->ipmbChannelUpdateSlaveAddress(slaveAddr);
933 };
934
935 static auto match = std::make_unique<sdbusplus::bus::match::match>(
936 static_cast<sdbusplus::bus::bus &>(*conn),
937 "type='signal',member='updateBmcSlaveAddr',", updateSlaveAddrHandler);
938}
939
Qiang XUbbfd00a2019-06-27 21:10:06 +0800940void addSendBroadcastHandler()
941{
942 // callback to handle dbus signal of sending broadcast message
943 std::function<void(sdbusplus::message::message &)> sendBroadcastHandler =
944 [](sdbusplus::message::message &message) {
945 uint8_t reqChannel, netFn, lun, cmd;
946 std::vector<uint8_t> dataReceived;
947 message.read(reqChannel, netFn, lun, cmd, dataReceived);
948
Kumar Thangavel950a2e82020-07-10 18:07:33 +0530949 IpmbChannel *channel = getChannel(reqChannel);
950
Qiang XUbbfd00a2019-06-27 21:10:06 +0800951 if (channel == nullptr)
952 {
953 phosphor::logging::log<phosphor::logging::level::ERR>(
954 "addSendBroadcastMsgHandler: requested channel does not "
955 "exist");
956 return;
957 }
958
959 uint8_t bmcSlaveAddress = channel->getBmcSlaveAddress();
960 uint8_t seqNum = 0; // seqNum is not used in broadcast msg
961 uint8_t targetAddr = broadcastAddress;
962
963 std::shared_ptr<IpmbRequest> request =
964 std::make_shared<IpmbRequest>(targetAddr, netFn, ipmbRsLun,
965 bmcSlaveAddress, seqNum, lun, cmd,
966 dataReceived);
967
968 std::shared_ptr<std::vector<uint8_t>> buffer =
969 std::make_shared<std::vector<uint8_t>>();
970
971 if (request->ipmbToi2cConstruct(*buffer) != 0)
972 {
973 return;
974 }
975
976 channel->ipmbSendI2cFrame(buffer);
977 };
978
979 static auto match = std::make_unique<sdbusplus::bus::match::match>(
980 static_cast<sdbusplus::bus::bus &>(*conn),
981 "type='signal',member='sendBroadcast',", sendBroadcastHandler);
982}
983
Dawid Fryckia642a942018-06-12 10:44:23 -0700984/**
985 * @brief Main
986 */
987int main(int argc, char *argv[])
988{
989 conn->request_name(ipmbBus);
990
991 auto server = sdbusplus::asio::object_server(conn);
992
Dawid Fryckia642a942018-06-12 10:44:23 -0700993 std::shared_ptr<sdbusplus::asio::dbus_interface> ipmbIface =
994 server.add_interface(ipmbObj, ipmbDbusIntf);
995
Dawid Fryckia642a942018-06-12 10:44:23 -0700996 ipmbIface->register_method("sendRequest", std::move(ipmbHandleRequest));
Dawid Fryckia642a942018-06-12 10:44:23 -0700997 ipmbIface->initialize();
998
999 if (initializeChannels() < 0)
1000 {
1001 phosphor::logging::log<phosphor::logging::level::ERR>(
1002 "Error initializeChannels");
1003 return -1;
1004 }
1005
Qiang XU8edcf1a2019-06-14 22:18:15 +08001006 addUpdateSlaveAddrHandler();
1007
Qiang XUbbfd00a2019-06-27 21:10:06 +08001008 addSendBroadcastHandler();
1009
Dawid Fryckia642a942018-06-12 10:44:23 -07001010 io.run();
1011 return 0;
1012}