blob: a49213e701c8cffd186b065b123c9a578028ab76 [file] [log] [blame]
Vernon Mauerya3702c12019-05-22 13:20:59 -07001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#include <errno.h>
18#include <fcntl.h>
Vernon Mauerya3702c12019-05-22 13:20:59 -070019#include <limits.h>
20#include <sys/stat.h>
21#include <sys/types.h>
22#include <unistd.h>
23
24#include <commandutils.hpp>
25#include <cstdint>
26#include <fstream>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +000027#include <ipmid/api.hpp>
Vernon Mauerya3702c12019-05-22 13:20:59 -070028#include <ipmid/utils.hpp>
29#include <phosphor-logging/log.hpp>
30#include <sdbusplus/bus.hpp>
31#include <sdbusplus/message/types.hpp>
32#include <smbiosmdrv2handler.hpp>
33#include <string>
34#include <vector>
35#include <xyz/openbmc_project/Common/error.hpp>
36#include <xyz/openbmc_project/Smbios/MDR_V2/error.hpp>
37
38std::unique_ptr<MDRV2> mdrv2 = nullptr;
39
40namespace variant_ns = sdbusplus::message::variant_ns;
41
42static void register_netfn_smbiosmdrv2_functions() __attribute__((constructor));
43static sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
44
45int MDRV2::agentLookup(const uint16_t &agentId)
46{
47 int agentIndex = -1;
48
49 if (lastAgentId == agentId)
50 {
51 return lastAgentIndex;
52 }
53
54 if (agentId == smbiosAgentId)
55 {
56 return firstAgentIndex;
57 }
58
59 return agentIndex;
60}
61
62int MDRV2::sdplusMdrv2GetProperty(const std::string &name,
63 sdbusplus::message::variant<uint8_t> &value,
64 const std::string &service)
65{
66 sdbusplus::message::message method =
67 bus.new_method_call(service.c_str(), mdrv2Path, dbusProperties, "Get");
68 method.append(mdrv2Interface, name);
69
70 sdbusplus::message::message reply = bus.call(method);
71
72 try
73 {
74 sdbusplus::message::message reply = bus.call(method);
75 reply.read(value);
76 }
77 catch (sdbusplus::exception_t &)
78 {
79 phosphor::logging::log<phosphor::logging::level::ERR>(
80 "Error get property, sdbusplus call failed");
81 return -1;
82 }
83
84 return 0;
85}
86
87int MDRV2::syncDirCommonData(uint8_t idIndex, uint32_t size,
88 const std::string &service)
89{
90 std::vector<uint32_t> commonData;
91 sdbusplus::message::message method =
92 bus.new_method_call(service.c_str(), mdrv2Path, mdrv2Interface,
93 "SynchronizeDirectoryCommonData");
94 method.append(idIndex, size);
95
96 try
97 {
98 sdbusplus::message::message reply = bus.call(method);
99 reply.read(commonData);
100 }
101 catch (sdbusplus::exception_t &)
102 {
103 phosphor::logging::log<phosphor::logging::level::ERR>(
104 "Error sync dir common data with service");
105 return -1;
106 }
107
108 if (commonData.size() < syncDirCommonSize)
109 {
110 phosphor::logging::log<phosphor::logging::level::ERR>(
111 "Error sync dir common data - data length invalid");
112 return -1;
113 }
114 smbiosDir.dir[idIndex].common.dataSetSize = commonData.at(0);
115 smbiosDir.dir[idIndex].common.dataVersion = commonData.at(1);
116 smbiosDir.dir[idIndex].common.timestamp = commonData.at(2);
117
118 return 0;
119}
120
121int MDRV2::findDataId(const uint8_t *dataInfo, const size_t &len,
122 const std::string &service)
123{
124 int idIndex = -1;
125
126 if (dataInfo == nullptr)
127 {
128 phosphor::logging::log<phosphor::logging::level::ERR>(
129 "Error dataInfo, input is null point");
130 return -1;
131 }
132
133 sdbusplus::message::message method = bus.new_method_call(
134 service.c_str(), mdrv2Path, mdrv2Interface, "FindIdIndex");
135 std::vector<uint8_t> info;
136 info.resize(len);
137 std::copy(dataInfo, dataInfo + len, info.data());
138 method.append(info);
139
140 try
141 {
142 sdbusplus::message::message reply = bus.call(method);
143 reply.read(idIndex);
144 }
145 catch (sdbusplus::exception_t &)
146 {
147 phosphor::logging::log<phosphor::logging::level::ERR>(
148 "Error find id index",
149 phosphor::logging::entry("SERVICE=%s", service.c_str()),
150 phosphor::logging::entry("PATH=%s", mdrv2Path));
151 return -1;
152 }
153
154 return idIndex;
155}
156
157uint16_t MDRV2::getSessionHandle(Mdr2DirStruct *dir)
158{
159 if (dir == NULL)
160 {
161 phosphor::logging::log<phosphor::logging::level::ERR>(
162 "Empty dir point");
163 return 0;
164 }
165 dir->sessionHandle++;
166 if (dir->sessionHandle == 0)
167 {
168 dir->sessionHandle = 1;
169 }
170
171 return dir->sessionHandle;
172}
173
174int MDRV2::findLockHandle(const uint16_t &lockHandle)
175{
176 int idIndex = -1;
177
178 for (int index = 0; index < smbiosDir.dirEntries; index++)
179 {
180 if (lockHandle == smbiosDir.dir[index].lockHandle)
181 {
182 return index;
183 }
184 }
185
186 return idIndex;
187}
188
189bool MDRV2::smbiosIsUpdating(uint8_t index)
190{
191 if (index > maxDirEntries)
192 {
193 return false;
194 }
195 if (smbiosDir.dir[index].stage == MDR2SMBIOSStatusEnum::mdr2Updating)
196 {
197 return true;
198 }
199
200 return false;
201}
202
203uint32_t MDRV2::calcChecksum32(uint8_t *buf, uint32_t len)
204{
205 uint32_t sum = 0;
206
207 if (buf == nullptr)
208 {
209 return invalidChecksum;
210 }
211
212 for (uint32_t index = 0; index < len; index++)
213 {
214 sum += buf[index];
215 }
216
217 return sum;
218}
219
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000220/** @brief implements mdr2 agent status command
221 * @param agentId
222 * @param dirVersion
223 *
224 * @returns IPMI completion code plus response data
225 * - mdrVersion
226 * - agentVersion
227 * - dirVersion
228 * - dirEntries
229 * - dataRequest
230 */
231ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t, uint8_t>
232 mdr2AgentStatus(uint16_t agentId, uint8_t dirVersion)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700233{
Vernon Mauerya3702c12019-05-22 13:20:59 -0700234 if (mdrv2 == nullptr)
235 {
236 mdrv2 = std::make_unique<MDRV2>();
237 }
238
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000239 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700240 if (agentIndex == -1)
241 {
242 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000243 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
244 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700245 }
246
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000247 constexpr uint8_t mdrVersion = mdr2Version;
248 constexpr uint8_t agentVersion = smbiosAgentVersion;
249 uint8_t dirVersionResp = mdrv2->smbiosDir.dirVersion;
250 uint8_t dirEntries = mdrv2->smbiosDir.dirEntries;
251 uint8_t dataRequest;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700252
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000253 if (mdrv2->smbiosDir.remoteDirVersion != dirVersion)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700254 {
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000255 mdrv2->smbiosDir.remoteDirVersion = dirVersion;
256 dataRequest =
Vernon Mauerya3702c12019-05-22 13:20:59 -0700257 static_cast<uint8_t>(DirDataRequestEnum::dirDataRequested);
258 }
259 else
260 {
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000261 dataRequest =
Vernon Mauerya3702c12019-05-22 13:20:59 -0700262 static_cast<uint8_t>(DirDataRequestEnum::dirDataNotRequested);
263 }
264
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000265 return ipmi::responseSuccess(mdrVersion, agentVersion, dirVersionResp,
266 dirEntries, dataRequest);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700267}
268
269ipmi_ret_t cmd_mdr2_get_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
270 ipmi_request_t request, ipmi_response_t response,
271 ipmi_data_len_t data_len, ipmi_context_t context)
272{
273 auto requestData = reinterpret_cast<const MDRiiGetDirRequest *>(request);
274 auto dataOut = reinterpret_cast<uint8_t *>(response);
275 std::vector<uint8_t> dirInfo;
276
277 if (*data_len != sizeof(MDRiiGetDirRequest))
278 {
279 *data_len = 0;
280 return IPMI_CC_REQ_DATA_LEN_INVALID;
281 }
282
283 *data_len = 0;
284
285 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
286
287 if (mdrv2 == nullptr)
288 {
289 mdrv2 = std::make_unique<MDRV2>();
290 }
291
292 int agentIndex = mdrv2->agentLookup(requestData->agentId);
293 if (agentIndex == -1)
294 {
295 phosphor::logging::log<phosphor::logging::level::ERR>(
296 "Unknown agent id",
297 phosphor::logging::entry("ID=%x", requestData->agentId));
298 return IPMI_CC_PARM_OUT_OF_RANGE;
299 }
300
301 sdbusplus::message::variant<uint8_t> value = 0;
302 if (0 != mdrv2->sdplusMdrv2GetProperty("DirectoryEntries", value, service))
303 {
304 phosphor::logging::log<phosphor::logging::level::ERR>(
305 "Error getting DirEnries");
306 return IPMI_CC_UNSPECIFIED_ERROR;
307 }
308 if (requestData->dirIndex > variant_ns::get<uint8_t>(value))
309 {
310 return IPMI_CC_PARM_OUT_OF_RANGE;
311 }
312
313 sdbusplus::message::message method = bus.new_method_call(
314 service.c_str(), mdrv2Path, mdrv2Interface, "GetDirectoryInformation");
315
316 method.append(requestData->dirIndex);
317
318 try
319 {
320 sdbusplus::message::message reply = bus.call(method);
321 reply.read(dirInfo);
322 }
323 catch (sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
324 InvalidParameter)
325 {
326 phosphor::logging::log<phosphor::logging::level::ERR>(
327 "Error get dir - Invalid parameter");
328 return IPMI_CC_PARM_OUT_OF_RANGE;
329 }
330 catch (sdbusplus::exception_t &)
331 {
332 phosphor::logging::log<phosphor::logging::level::ERR>(
333 "Error get dir",
334 phosphor::logging::entry("SERVICE=%s", service.c_str()),
335 phosphor::logging::entry("PATH=%s", mdrv2Path));
336 return IPMI_CC_RESPONSE_ERROR;
337 }
338
339 if (dirInfo.size() < sizeof(MDRiiGetDirResponse))
340 {
341 phosphor::logging::log<phosphor::logging::level::ERR>(
342 "Error get dir, response length invalid");
343 return IPMI_CC_UNSPECIFIED_ERROR;
344 }
345
346 auto responseData = reinterpret_cast<MDRiiGetDirResponse *>(dirInfo.data());
347
348 *data_len = dirInfo.size();
349
350 if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
351 // than MAX_IPMI_BUFFER
352 {
353 phosphor::logging::log<phosphor::logging::level::ERR>(
354 "Data length send from service is invalid");
355 *data_len = 0;
356 return IPMI_CC_RESPONSE_ERROR;
357 }
358
359 std::copy(&dirInfo[0], &dirInfo[*data_len], dataOut);
360
361 return IPMI_CC_OK;
362}
363
364ipmi_ret_t cmd_mdr2_send_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
365 ipmi_request_t request, ipmi_response_t response,
366 ipmi_data_len_t data_len, ipmi_context_t context)
367{
368 auto requestData = reinterpret_cast<const MDRiiSendDirRequest *>(request);
369 std::vector<uint8_t> idVector;
370 bool teminate = false;
371
372 if (*data_len != sizeof(MDRiiSendDirRequest))
373 {
374 *data_len = 0;
375 return IPMI_CC_REQ_DATA_LEN_INVALID;
376 }
377
378 *data_len = 0;
379
380 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
381
382 if (mdrv2 == nullptr)
383 {
384 mdrv2 = std::make_unique<MDRV2>();
385 }
386
387 int agentIndex = mdrv2->agentLookup(requestData->agentId);
388 if (agentIndex == -1)
389 {
390 phosphor::logging::log<phosphor::logging::level::ERR>(
391 "Unknown agent id",
392 phosphor::logging::entry("ID=%x", requestData->agentId));
393 return IPMI_CC_PARM_OUT_OF_RANGE;
394 }
395
396 if ((requestData->dirIndex + requestData->returnedEntries) > maxDirEntries)
397 {
398 phosphor::logging::log<phosphor::logging::level::ERR>(
399 "Too many directory entries");
400 return IPMI_CC_STORGE_LEAK;
401 }
402
403 sdbusplus::message::message method = bus.new_method_call(
404 service.c_str(), mdrv2Path, mdrv2Interface, "SendDirectoryInformation");
405 method.append(requestData->dirVersion, requestData->dirIndex,
406 requestData->returnedEntries, requestData->remainingEntries);
407 uint8_t *reqPoint;
408 for (int index = 0; index < requestData->returnedEntries; index++)
409 {
410 reqPoint = (uint8_t *)&(requestData->data[index]);
411 std::copy(reqPoint, sizeof(Mdr2DirEntry) + reqPoint, idVector.data());
412 }
413 method.append(idVector);
414
415 try
416 {
417 sdbusplus::message::message reply = bus.call(method);
418 reply.read(teminate);
419 }
420 catch (sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
421 InvalidParameter)
422 {
423 phosphor::logging::log<phosphor::logging::level::ERR>(
424 "Error send dir - Invalid parameter");
425 return IPMI_CC_PARM_OUT_OF_RANGE;
426 }
427 catch (sdbusplus::exception_t &)
428 {
429 phosphor::logging::log<phosphor::logging::level::ERR>(
430 "Error send dir",
431 phosphor::logging::entry("SERVICE=%s", service.c_str()),
432 phosphor::logging::entry("PATH=%s", mdrv2Path));
433 return IPMI_CC_RESPONSE_ERROR;
434 }
435
436 *data_len = 1;
437 if (teminate == false)
438 *(static_cast<uint8_t *>(response)) = 0;
439 else
440 *(static_cast<uint8_t *>(response)) = 1;
441 return IPMI_CC_OK;
442}
443
444ipmi_ret_t cmd_mdr2_get_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
445 ipmi_request_t request,
446 ipmi_response_t response,
447 ipmi_data_len_t data_len,
448 ipmi_context_t context)
449{
450 auto requestData =
451 reinterpret_cast<const MDRiiGetDataInfoRequest *>(request);
452 auto dataOut = reinterpret_cast<uint8_t *>(response);
453 std::vector<uint8_t> res;
454
455 if (*data_len < sizeof(MDRiiGetDataInfoRequest))
456 {
457 *data_len = 0;
458 return IPMI_CC_REQ_DATA_LEN_INVALID;
459 }
460
461 *data_len = 0;
462
463 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
464
465 if (mdrv2 == nullptr)
466 {
467 mdrv2 = std::make_unique<MDRV2>();
468 }
469
470 int agentIndex = mdrv2->agentLookup(requestData->agentId);
471 if (agentIndex == -1)
472 {
473 phosphor::logging::log<phosphor::logging::level::ERR>(
474 "Unknown agent id",
475 phosphor::logging::entry("ID=%x", requestData->agentId));
476 return IPMI_CC_PARM_OUT_OF_RANGE;
477 }
478
479 int idIndex =
480 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
481 sizeof(requestData->dataSetInfo.dataInfo), service);
482
483 if ((idIndex < 0) || (idIndex >= maxDirEntries))
484 {
485 phosphor::logging::log<phosphor::logging::level::ERR>(
486 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
487 return IPMI_CC_PARM_OUT_OF_RANGE;
488 }
489
490 sdbusplus::message::message method = bus.new_method_call(
491 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataInformation");
492
493 method.append(idIndex);
494
495 try
496 {
497 sdbusplus::message::message reply = bus.call(method);
498 reply.read(res);
499 }
500 catch (sdbusplus::exception_t &)
501 {
502 phosphor::logging::log<phosphor::logging::level::ERR>(
503 "Error get data info",
504 phosphor::logging::entry("SERVICE=%s", service.c_str()),
505 phosphor::logging::entry("PATH=%s", mdrv2Path));
506 return IPMI_CC_RESPONSE_ERROR;
507 }
508
509 if (res.size() != sizeof(MDRiiGetDataInfoResponse))
510 {
511 phosphor::logging::log<phosphor::logging::level::ERR>(
512 "Get data info response length not invalid");
513 return IPMI_CC_UNSPECIFIED_ERROR;
514 }
515 *data_len = static_cast<size_t>(res.size());
516 std::copy(&res[0], &res[*data_len], dataOut);
517
518 return IPMI_CC_OK;
519}
520
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000521/** @brief implements mdr2 data info offer command
522 * @param agentId - Offer a agent ID to get the "Data Set ID"
523 *
524 * @returns IPMI completion code plus response data
525 * - dataInfo
526 */
527ipmi::RspType<std::vector<uint8_t>> mdr2DataInfoOffer(uint16_t agentId)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700528{
Vernon Mauerya3702c12019-05-22 13:20:59 -0700529 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
530
531 if (mdrv2 == nullptr)
532 {
533 mdrv2 = std::make_unique<MDRV2>();
534 }
535
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000536 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700537 if (agentIndex == -1)
538 {
539 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000540 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
541 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700542 }
543
544 sdbusplus::message::message method = bus.new_method_call(
545 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataOffer");
546
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000547 std::vector<uint8_t> dataInfo;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700548 try
549 {
550 sdbusplus::message::message reply = bus.call(method);
551 reply.read(dataInfo);
552 }
553 catch (
554 sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::UpdateInProgress
555 &)
556 {
557 phosphor::logging::log<phosphor::logging::level::ERR>(
558 "Send data info offer failed - not available to update data "
559 "into agent at present");
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000560 return ipmi::responseCommandNotAvailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700561 }
562 catch (sdbusplus::exception_t &)
563 {
564 phosphor::logging::log<phosphor::logging::level::ERR>(
565 "Error send data info offer",
566 phosphor::logging::entry("SERVICE=%s", service.c_str()),
567 phosphor::logging::entry("PATH=%s", mdrv2Path));
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000568 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700569 }
570
571 if (dataInfo.size() != sizeof(MDRiiOfferDataInfoResponse))
572 {
573 phosphor::logging::log<phosphor::logging::level::ERR>(
574 "Error send data info offer, return length invalid");
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000575 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700576 }
577
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000578 return ipmi::responseSuccess(dataInfo);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700579}
580
581ipmi_ret_t cmd_mdr2_send_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
582 ipmi_request_t request,
583 ipmi_response_t response,
584 ipmi_data_len_t data_len,
585 ipmi_context_t context)
586{
587 auto requestData =
588 reinterpret_cast<const MDRiiSendDataInfoRequest *>(request);
589 bool entryChanged = true;
590
591 if (*data_len != sizeof(MDRiiSendDataInfoRequest))
592 {
593 *data_len = 0;
594 return IPMI_CC_REQ_DATA_LEN_INVALID;
595 }
596
597 *data_len = 0;
598
599 if (requestData->dataLength > smbiosTableStorageSize)
600 {
601 phosphor::logging::log<phosphor::logging::level::ERR>(
602 "Requested data length is out of SMBIOS Table storage size.");
603 return IPMI_CC_PARM_OUT_OF_RANGE;
604 }
605
606 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
607
608 if (mdrv2 == nullptr)
609 {
610 mdrv2 = std::make_unique<MDRV2>();
611 }
612
613 int agentIndex = mdrv2->agentLookup(requestData->agentId);
614 if (agentIndex == -1)
615 {
616 phosphor::logging::log<phosphor::logging::level::ERR>(
617 "Unknown agent id",
618 phosphor::logging::entry("ID=%x", requestData->agentId));
619 return IPMI_CC_PARM_OUT_OF_RANGE;
620 }
621
622 int idIndex =
623 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
624 sizeof(requestData->dataSetInfo.dataInfo), service);
625
626 if ((idIndex < 0) || (idIndex >= maxDirEntries))
627 {
628 phosphor::logging::log<phosphor::logging::level::ERR>(
629 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
630 return IPMI_CC_PARM_OUT_OF_RANGE;
631 }
632
633 sdbusplus::message::message method = bus.new_method_call(
634 service.c_str(), mdrv2Path, mdrv2Interface, "SendDataInformation");
635
636 method.append((uint8_t)idIndex, requestData->validFlag,
637 requestData->dataLength, requestData->dataVersion,
638 requestData->timeStamp);
639
640 try
641 {
642 sdbusplus::message::message reply = bus.call(method);
643 reply.read(entryChanged);
644 }
645 catch (sdbusplus::exception_t &)
646 {
647 phosphor::logging::log<phosphor::logging::level::ERR>(
648 "Error send data info",
649 phosphor::logging::entry("SERVICE=%s", service.c_str()),
650 phosphor::logging::entry("PATH=%s", mdrv2Path));
651 return IPMI_CC_RESPONSE_ERROR;
652 }
653
654 *data_len = 1;
655
656 if (entryChanged)
657 {
658 *(static_cast<uint8_t *>(response)) = 1;
659 }
660 else
661 {
662 *(static_cast<uint8_t *>(response)) = 0;
663 }
664
665 return IPMI_CC_OK;
666}
667
668ipmi_ret_t cmd_mdr2_get_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
669 ipmi_request_t request,
670 ipmi_response_t response,
671 ipmi_data_len_t data_len,
672 ipmi_context_t context)
673{
674 auto requestData =
675 reinterpret_cast<const MDRiiGetDataBlockRequest *>(request);
676 auto responseData = reinterpret_cast<MDRiiGetDataBlockResponse *>(response);
677 std::tuple<uint8_t, uint32_t, uint32_t, std::vector<uint8_t>> res;
678 std::vector<uint8_t> resData;
679 uint8_t status = 1;
680
681 if (*data_len != sizeof(MDRiiGetDataBlockRequest))
682 {
683 *data_len = 0;
684 return IPMI_CC_REQ_DATA_LEN_INVALID;
685 }
686
687 *data_len = 0;
688
689 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
690
691 if (mdrv2 == nullptr)
692 {
693 mdrv2 = std::make_unique<MDRV2>();
694 }
695
696 int agentIndex = mdrv2->agentLookup(requestData->agentId);
697 if (agentIndex == -1)
698 {
699 phosphor::logging::log<phosphor::logging::level::ERR>(
700 "Unknown agent id",
701 phosphor::logging::entry("ID=%x", requestData->agentId));
702 return IPMI_CC_PARM_OUT_OF_RANGE;
703 }
704
705 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
706
707 if ((idIndex < 0) || (idIndex >= maxDirEntries))
708 {
709 phosphor::logging::log<phosphor::logging::level::ERR>(
710 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
711 return IPMI_CC_PARM_OUT_OF_RANGE;
712 }
713
714 if (requestData->xferOffset >= mdrv2->smbiosDir.dir[idIndex].common.size)
715 {
716 phosphor::logging::log<phosphor::logging::level::ERR>(
717 "Offset is outside of range.");
718 return IPMI_CC_PARM_OUT_OF_RANGE;
719 }
720
721 size_t outSize =
722 (requestData->xferLength > mdrv2->smbiosDir.dir[idIndex].xferSize)
723 ? mdrv2->smbiosDir.dir[idIndex].xferSize
724 : requestData->xferLength;
725 if (outSize > UINT_MAX - requestData->xferOffset)
726 {
727 phosphor::logging::log<phosphor::logging::level::ERR>(
728 "Out size and offset are out of range");
729 return IPMI_CC_PARM_OUT_OF_RANGE;
730 }
731 if ((requestData->xferOffset + outSize) >
732 mdrv2->smbiosDir.dir[idIndex].common.size)
733 {
734 outSize =
735 mdrv2->smbiosDir.dir[idIndex].common.size - requestData->xferOffset;
736 }
737
738 responseData->xferLength = outSize;
739 if (responseData->xferLength > requestData->xferLength)
740 {
741 phosphor::logging::log<phosphor::logging::level::ERR>(
742 "Get data block unexpected error.");
743 return IPMI_CC_UNSPECIFIED_ERROR;
744 }
745
746 if ((requestData->xferOffset + outSize) >
747 UINT_MAX -
748 reinterpret_cast<size_t>(mdrv2->smbiosDir.dir[idIndex].dataStorage))
749 {
750 phosphor::logging::log<phosphor::logging::level::ERR>(
751 "Input data to calculate checksum is out of range");
752 return IPMI_CC_PARM_OUT_OF_RANGE;
753 }
754
755 uint32_t u32Checksum = mdrv2->calcChecksum32(
756 mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset,
757 outSize);
758 if (u32Checksum == invalidChecksum)
759 {
760 phosphor::logging::log<phosphor::logging::level::ERR>(
761 "Get data block failed - invalid checksum");
762 return IPMI_CC_OEM_INVALID_CHECKSUM;
763 }
764 responseData->checksum = u32Checksum;
765
766 *data_len = sizeof(responseData->xferLength) +
767 sizeof(responseData->checksum) + outSize;
768
769 if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
770 // than MAX_IPMI_BUFFER
771 {
772 phosphor::logging::log<phosphor::logging::level::ERR>(
773 "Data length send from service is invalid");
774 *data_len = 0;
775 return IPMI_CC_RESPONSE_ERROR;
776 }
777
778 std::copy(
779 &mdrv2->smbiosDir.dir[idIndex].dataStorage[requestData->xferOffset],
780 &mdrv2->smbiosDir.dir[idIndex]
781 .dataStorage[requestData->xferOffset + outSize],
782 responseData->data);
783
784 return IPMI_CC_OK;
785}
786
787ipmi_ret_t cmd_mdr2_send_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
788 ipmi_request_t request,
789 ipmi_response_t response,
790 ipmi_data_len_t data_len,
791 ipmi_context_t context)
792{
793 auto requestData =
794 reinterpret_cast<const MDRiiSendDataBlockRequest *>(request);
795
796 if (*data_len != sizeof(MDRiiSendDataBlockRequest))
797 {
798 *data_len = 0;
799 return IPMI_CC_REQ_DATA_LEN_INVALID;
800 }
801
802 *data_len = 0;
803
804 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
805
806 if (mdrv2 == nullptr)
807 {
808 mdrv2 = std::make_unique<MDRV2>();
809 }
810
811 int agentIndex = mdrv2->agentLookup(requestData->agentId);
812 if (agentIndex == -1)
813 {
814 phosphor::logging::log<phosphor::logging::level::ERR>(
815 "Unknown agent id",
816 phosphor::logging::entry("ID=%x", requestData->agentId));
817 return IPMI_CC_PARM_OUT_OF_RANGE;
818 }
819
820 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
821
822 if ((idIndex < 0) || (idIndex >= maxDirEntries))
823 {
824 phosphor::logging::log<phosphor::logging::level::ERR>(
825 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
826 return IPMI_CC_PARM_OUT_OF_RANGE;
827 }
828
829 if (mdrv2->smbiosIsUpdating(idIndex))
830 {
831 if (requestData->xferOffset > UINT_MAX - requestData->xferLength)
832 {
833 phosphor::logging::log<phosphor::logging::level::ERR>(
834 "Offset and length are out of range");
835 return IPMI_CC_PARM_OUT_OF_RANGE;
836 }
837 if (((requestData->xferOffset + requestData->xferLength) >
838 mdrv2->smbiosDir.dir[idIndex].maxDataSize) ||
839 ((requestData->xferOffset + requestData->xferLength) >
840 mdrv2->smbiosDir.dir[idIndex].common.dataSetSize))
841 {
842 phosphor::logging::log<phosphor::logging::level::ERR>(
843 "Send data block Invalid offset/length");
844 return IPMI_CC_REQUEST_DATA_FIELD_LENGTH_LIMIT_EXCEEDED;
845 }
846 if (reinterpret_cast<size_t>(
847 mdrv2->smbiosDir.dir[idIndex].dataStorage) >
848 UINT_MAX - requestData->xferOffset)
849 {
850 phosphor::logging::log<phosphor::logging::level::ERR>(
851 "Offset is out of range");
852 return IPMI_CC_PARM_OUT_OF_RANGE;
853 }
854 uint8_t *destAddr =
855 mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset;
856 uint8_t *sourceAddr = reinterpret_cast<uint8_t *>(mdrv2->area->vPtr);
857 uint32_t calcChecksum =
858 mdrv2->calcChecksum32(sourceAddr, requestData->xferLength);
859 if (calcChecksum != requestData->checksum)
860 {
861 phosphor::logging::log<phosphor::logging::level::ERR>(
862 "Send data block Invalid checksum");
863 return IPMI_CC_OEM_INVALID_CHECKSUM;
864 }
865 else
866 {
867 if (reinterpret_cast<size_t>(sourceAddr) >
868 UINT_MAX - requestData->xferLength)
869 {
870 phosphor::logging::log<phosphor::logging::level::ERR>(
871 "Length is out of range");
872 return IPMI_CC_PARM_OUT_OF_RANGE;
873 }
874 std::copy(sourceAddr, sourceAddr + requestData->xferLength,
875 destAddr);
876 }
877 }
878 else
879 {
880 phosphor::logging::log<phosphor::logging::level::ERR>(
881 "Send data block failed, other data is updating");
882 return IPMI_CC_DESTINATION_UNAVAILABLE;
883 }
884
885 return IPMI_CC_OK;
886}
887
888bool MDRV2::storeDatatoFlash(MDRSMBIOSHeader *mdrHdr, uint8_t *data)
889{
890 std::ofstream smbiosFile(mdrType2File,
891 std::ios_base::binary | std::ios_base::trunc);
892 if (!smbiosFile.good())
893 {
894 phosphor::logging::log<phosphor::logging::level::ERR>(
895 "Write data from flash error - Open MDRV2 table file failure");
896 return false;
897 }
898
899 try
900 {
901 smbiosFile.write(reinterpret_cast<char *>(mdrHdr),
902 sizeof(MDRSMBIOSHeader));
903 smbiosFile.write(reinterpret_cast<char *>(data), mdrHdr->dataSize);
904 }
905 catch (std::ofstream::failure &e)
906 {
907 phosphor::logging::log<phosphor::logging::level::ERR>(
908 "Write data from flash error - write data error");
909 return false;
910 }
911
912 return true;
913}
914
915void SharedMemoryArea::Initialize(uint32_t addr, uint32_t areaSize)
916{
917 int memDriver = 0;
918
919 // open mem driver for the system memory access
920 memDriver = open("/dev/vgasharedmem", O_RDONLY);
921 if (memDriver < 0)
922 {
923 phosphor::logging::log<phosphor::logging::level::ERR>(
924 "Cannot access mem driver");
925 throw std::system_error(EIO, std::generic_category());
926 }
927
928 // map the system memory
929 vPtr = mmap(NULL, // where to map to: don't mind
930 areaSize, // how many bytes ?
931 PROT_READ, // want to read and write
932 MAP_SHARED, // no copy on write
933 memDriver, // handle to /dev/mem
934 (physicalAddr & pageMask)); // hopefully the Text-buffer :-)
935
936 close(memDriver);
937 if (vPtr == MAP_FAILED)
938 {
939 phosphor::logging::log<phosphor::logging::level::ERR>(
940 "Failed to map share memory");
941 throw std::system_error(EIO, std::generic_category());
942 }
943 size = areaSize;
944 physicalAddr = addr;
945}
946
947bool MDRV2::smbiosUnlock(uint8_t index)
948{
949 bool ret;
950 switch (smbiosDir.dir[index].stage)
951 {
952 case MDR2SMBIOSStatusEnum::mdr2Updating:
953 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updated;
954 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
955
956 timer->stop();
957 smbiosDir.dir[index].lockHandle = 0;
958 ret = true;
959 break;
960
961 case MDR2SMBIOSStatusEnum::mdr2Updated:
962 case MDR2SMBIOSStatusEnum::mdr2Loaded:
963 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
964
965 timer->stop();
966
967 smbiosDir.dir[index].lockHandle = 0;
968 ret = true;
969 break;
970
971 default:
972 break;
973 }
974
975 return ret;
976}
977
978bool MDRV2::smbiosTryLock(uint8_t flag, uint8_t index, uint16_t *session,
979 uint16_t timeout)
980{
981 bool ret = false;
982 uint32_t u32Status = 0;
983
984 if (timeout == 0)
985 {
986 timeout = defaultTimeout;
987 }
988 std::chrono::microseconds usec(timeout * sysClock);
989
990 switch (smbiosDir.dir[index].stage)
991 {
992 case MDR2SMBIOSStatusEnum::mdr2Updating:
993 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
994 {
995 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
996 timer->start(usec);
997 lockIndex = index;
998
999 *session = getSessionHandle(&smbiosDir);
1000 smbiosDir.dir[index].lockHandle = *session;
1001 ret = true;
1002 }
1003 break;
1004 case MDR2SMBIOSStatusEnum::mdr2Init:
1005 if (flag)
1006 {
1007 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updating;
1008 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
1009 timer->start(usec);
1010 lockIndex = index;
1011
1012 *session = getSessionHandle(&smbiosDir);
1013 smbiosDir.dir[index].lockHandle = *session;
1014 ret = true;
1015 }
1016 break;
1017
1018 case MDR2SMBIOSStatusEnum::mdr2Updated:
1019 case MDR2SMBIOSStatusEnum::mdr2Loaded:
1020 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
1021 {
1022 if (flag)
1023 {
1024 smbiosDir.dir[index].stage =
1025 MDR2SMBIOSStatusEnum::mdr2Updating;
1026 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
1027 }
1028 else
1029 {
1030 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
1031 }
1032
1033 timer->start(usec);
1034 lockIndex = index;
1035
1036 *session = getSessionHandle(&smbiosDir);
1037 smbiosDir.dir[index].lockHandle = *session;
1038 ret = true;
1039 }
1040 break;
1041
1042 default:
1043 break;
1044 }
1045 return ret;
1046}
1047
1048void MDRV2::timeoutHandler()
1049{
1050 smbiosUnlock(lockIndex);
1051 mdrv2->area.reset(nullptr);
1052}
1053
1054ipmi_ret_t cmd_mdr2_lock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1055 ipmi_request_t request, ipmi_response_t response,
1056 ipmi_data_len_t data_len, ipmi_context_t context)
1057{
1058 auto requestData = reinterpret_cast<const MDRiiLockDataRequest *>(request);
1059 auto responseData = reinterpret_cast<MDRiiLockDataResponse *>(response);
1060 uint16_t session = 0;
1061
1062 std::tuple<bool, uint8_t, uint16_t, uint32_t, uint32_t, uint32_t> res;
1063
1064 if (*data_len < sizeof(MDRiiLockDataRequest))
1065 {
1066 *data_len = 0;
1067 return IPMI_CC_REQ_DATA_LEN_INVALID;
1068 }
1069
1070 *data_len = 0;
1071
1072 if (mdrv2 == nullptr)
1073 {
1074 mdrv2 = std::make_unique<MDRV2>();
1075 }
1076
1077 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1078 if (agentIndex == -1)
1079 {
1080 phosphor::logging::log<phosphor::logging::level::ERR>(
1081 "Unknown agent id",
1082 phosphor::logging::entry("ID=%x", requestData->agentId));
1083 return IPMI_CC_PARM_OUT_OF_RANGE;
1084 }
1085
1086 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1087
1088 int idIndex =
1089 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
1090 sizeof(requestData->dataSetInfo.dataInfo), service);
1091
1092 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1093 {
1094 phosphor::logging::log<phosphor::logging::level::ERR>(
1095 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1096 return IPMI_CC_PARM_OUT_OF_RANGE;
1097 }
1098
1099 if (!mdrv2->smbiosTryLock(0, idIndex, &session, requestData->timeout))
1100 {
1101 phosphor::logging::log<phosphor::logging::level::ERR>(
1102 "Lock Data failed - cannot lock idIndex");
1103 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
1104 }
1105
1106 *data_len = sizeof(MDRiiLockDataResponse);
1107
1108 responseData->mdrVersion = mdr2Version;
1109 responseData->lockHandle = session;
1110 responseData->dataLength = mdrv2->smbiosDir.dir[idIndex].common.size;
1111 responseData->xferAddress = mdrv2->smbiosDir.dir[idIndex].xferBuff;
1112 responseData->xferLength = mdrv2->smbiosDir.dir[idIndex].xferSize;
1113
1114 return IPMI_CC_OK;
1115}
1116
1117ipmi_ret_t cmd_mdr2_unlock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1118 ipmi_request_t request,
1119 ipmi_response_t response,
1120 ipmi_data_len_t data_len,
1121 ipmi_context_t context)
1122{
1123 phosphor::logging::log<phosphor::logging::level::ERR>("unlock data");
1124 auto requestData =
1125 reinterpret_cast<const MDRiiUnlockDataRequest *>(request);
1126
1127 if (*data_len != sizeof(MDRiiUnlockDataRequest))
1128 {
1129 *data_len = 0;
1130 return IPMI_CC_REQ_DATA_LEN_INVALID;
1131 }
1132
1133 *data_len = 0;
1134
1135 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1136
1137 if (mdrv2 == nullptr)
1138 {
1139 mdrv2 = std::make_unique<MDRV2>();
1140 }
1141
1142 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1143 if (agentIndex == -1)
1144 {
1145 phosphor::logging::log<phosphor::logging::level::ERR>(
1146 "Unknown agent id",
1147 phosphor::logging::entry("ID=%x", requestData->agentId));
1148 return IPMI_CC_PARM_OUT_OF_RANGE;
1149 }
1150
1151 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
1152
1153 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1154 {
1155 phosphor::logging::log<phosphor::logging::level::ERR>(
1156 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1157 return IPMI_CC_PARM_OUT_OF_RANGE;
1158 }
1159
1160 if (!mdrv2->smbiosUnlock(idIndex))
1161 {
1162 phosphor::logging::log<phosphor::logging::level::ERR>(
1163 "Unlock Data failed - cannot unlock idIndex");
1164 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
1165 }
1166
1167 return IPMI_CC_OK;
1168}
1169
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001170/**
1171@brief This command is executed after POST BIOS to get the session info.
1172
1173@param - agentId, dataInfo, dataLength, xferAddress, xferLength, timeout.
1174
1175@return xferStartAck and session on success.
1176**/
1177ipmi::RspType<uint8_t, uint16_t>
1178 cmd_mdr2_data_start(uint16_t agentId, std::array<uint8_t, 16> dataInfo,
1179 uint32_t dataLength, uint32_t xferAddress,
1180 uint32_t xferLength, uint16_t timeout)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001181{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001182 uint16_t session = 0;
1183
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001184 if (dataLength > smbiosTableStorageSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001185 {
1186 phosphor::logging::log<phosphor::logging::level::ERR>(
1187 "Requested data length is out of SMBIOS Table storage size.");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001188 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001189 }
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001190 if ((xferLength + xferAddress) > mdriiSMSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001191 {
1192 phosphor::logging::log<phosphor::logging::level::ERR>(
1193 "Invalid data address and size");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001194 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001195 }
1196
1197 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1198
1199 if (mdrv2 == nullptr)
1200 {
1201 mdrv2 = std::make_unique<MDRV2>();
1202 }
1203
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001204 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001205 if (agentIndex == -1)
1206 {
1207 phosphor::logging::log<phosphor::logging::level::ERR>(
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001208 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1209 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001210 }
1211
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001212 int idIndex = mdrv2->findDataId(dataInfo.data(), sizeof(dataInfo), service);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001213
1214 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1215 {
1216 phosphor::logging::log<phosphor::logging::level::ERR>(
1217 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001218 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001219 }
1220
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001221 if (mdrv2->smbiosTryLock(1, idIndex, &session, timeout))
Vernon Mauerya3702c12019-05-22 13:20:59 -07001222 {
1223 try
1224 {
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001225 mdrv2->area =
1226 std::make_unique<SharedMemoryArea>(xferAddress, xferLength);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001227 }
1228 catch (const std::system_error &e)
1229 {
1230 mdrv2->smbiosUnlock(idIndex);
1231 phosphor::logging::log<phosphor::logging::level::ERR>(
1232 "Unable to access share memory");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001233 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001234 }
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001235 mdrv2->smbiosDir.dir[idIndex].common.size = dataLength;
Vernon Mauerya3702c12019-05-22 13:20:59 -07001236 mdrv2->smbiosDir.dir[idIndex].lockHandle = session;
1237 if (-1 ==
1238 mdrv2->syncDirCommonData(
1239 idIndex, mdrv2->smbiosDir.dir[idIndex].common.size, service))
1240 {
1241 phosphor::logging::log<phosphor::logging::level::ERR>(
1242 "Unable to sync data to service");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001243 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001244 }
1245 }
1246 else
1247 {
1248 phosphor::logging::log<phosphor::logging::level::ERR>(
1249 "Canot lock smbios");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001250 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001251 }
1252
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001253 static constexpr uint8_t xferStartAck = 1;
Vernon Mauerya3702c12019-05-22 13:20:59 -07001254
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001255 return ipmi::responseSuccess(xferStartAck, session);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001256}
1257
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001258/**
1259@brief This command is executed to close the session.
1260
1261@param - agentId, lockHandle.
1262
1263@return completion code on success.
1264**/
1265ipmi::RspType<> cmd_mdr2_data_done(uint16_t agentId, uint16_t lockHandle)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001266{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001267
1268 if (mdrv2 == nullptr)
1269 {
1270 mdrv2 = std::make_unique<MDRV2>();
1271 }
1272
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001273 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001274 if (agentIndex == -1)
1275 {
1276 phosphor::logging::log<phosphor::logging::level::ERR>(
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001277 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1278 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001279 }
1280
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001281 int idIndex = mdrv2->findLockHandle(lockHandle);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001282
1283 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1284 {
1285 phosphor::logging::log<phosphor::logging::level::ERR>(
1286 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001287 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001288 }
1289
1290 if (!mdrv2->smbiosUnlock(idIndex))
1291 {
1292 phosphor::logging::log<phosphor::logging::level::ERR>(
1293 "Send data done failed - cannot unlock idIndex");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001294 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001295 }
1296
1297 mdrv2->area.reset(nullptr);
1298 MDRSMBIOSHeader mdr2Smbios;
1299 mdr2Smbios.mdrType = mdrTypeII;
1300 mdr2Smbios.dirVer = mdrv2->smbiosDir.dir[0].common.dataVersion;
1301 mdr2Smbios.timestamp = mdrv2->smbiosDir.dir[0].common.timestamp;
1302 mdr2Smbios.dataSize = mdrv2->smbiosDir.dir[0].common.size;
1303
1304 if (access(smbiosPath, 0) == -1)
1305 {
1306 int flag = mkdir(smbiosPath, S_IRWXU);
1307 if (flag != 0)
1308 {
1309 phosphor::logging::log<phosphor::logging::level::ERR>(
1310 "create folder failed for writting smbios file");
1311 }
1312 }
1313 if (!mdrv2->storeDatatoFlash(
1314 &mdr2Smbios, mdrv2->smbiosDir.dir[smbiosDirIndex].dataStorage))
1315 {
1316 phosphor::logging::log<phosphor::logging::level::ERR>(
1317 "MDR2 Store data to flash failed");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001318 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001319 }
Vernon Mauerya3702c12019-05-22 13:20:59 -07001320 bool status = false;
1321 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1322 sdbusplus::message::message method = bus.new_method_call(
1323 service.c_str(), mdrv2Path, mdrv2Interface, "AgentSynchronizeData");
1324
1325 try
1326 {
1327 sdbusplus::message::message reply = bus.call(method);
1328 reply.read(status);
1329 }
1330 catch (sdbusplus::exception_t &)
1331 {
1332 phosphor::logging::log<phosphor::logging::level::ERR>(
1333 "Error Sync data with service",
1334 phosphor::logging::entry("SERVICE=%s", service.c_str()),
1335 phosphor::logging::entry("PATH=%s", mdrv2Path));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001336 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001337 }
1338
1339 if (!status)
1340 {
1341 phosphor::logging::log<phosphor::logging::level::ERR>(
1342 "Sync data with service failure");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001343 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001344 }
1345
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001346 return ipmi::responseSuccess();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001347}
1348
1349static void register_netfn_smbiosmdrv2_functions(void)
1350{
1351 // MDR V2 Command
1352 // <Get MDRII Status Command>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001353 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1354 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_AGENT_STATUS,
1355 ipmi::Privilege::Operator, mdr2AgentStatus);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001356
1357 // <Get MDRII Directory Command>
1358 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1359 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DIR, NULL,
1360 cmd_mdr2_get_dir, PRIVILEGE_OPERATOR);
1361
1362 // <Send MDRII Directory Command>
1363 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1364 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DIR, NULL,
1365 cmd_mdr2_send_dir, PRIVILEGE_OPERATOR);
1366
1367 // <Get MDRII Data Info Command>
1368 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1369 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_INFO,
1370 NULL, cmd_mdr2_get_data_info, PRIVILEGE_OPERATOR);
1371
1372 // <Send MDRII Info Offer>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001373 ipmi::registerHandler(
1374 ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1375 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO_OFFER,
1376 ipmi::Privilege::Operator, mdr2DataInfoOffer);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001377
1378 // <Send MDRII Data Info>
1379 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1380 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO,
1381 NULL, cmd_mdr2_send_data_info, PRIVILEGE_OPERATOR);
1382
1383 // <Get MDRII Data Block Command>
1384 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1385 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_BLOCK,
1386 NULL, cmd_mdr2_get_data_block, PRIVILEGE_OPERATOR);
1387
1388 // <Send MDRII Data Block>
1389 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1390 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_BLOCK,
1391 NULL, cmd_mdr2_send_data_block, PRIVILEGE_OPERATOR);
1392
1393 // <Lock MDRII Data Command>
1394 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1395 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_LOCK_DATA, NULL,
1396 cmd_mdr2_lock_data, PRIVILEGE_OPERATOR);
1397
1398 // <Unlock MDRII Data Command>
1399 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1400 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_UNLOCK_DATA,
1401 NULL, cmd_mdr2_unlock_data, PRIVILEGE_OPERATOR);
1402
1403 // <Send MDRII Data Start>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001404 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1405 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_START,
1406 ipmi::Privilege::Operator, cmd_mdr2_data_start);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001407
1408 // <Send MDRII Data Done>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001409 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1410 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_DONE,
1411 ipmi::Privilege::Operator, cmd_mdr2_data_done);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001412}