blob: da3712ab3e96745d24bbc844bbb25adbe5621b2a [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>
19#include <ipmid/api.h>
20#include <limits.h>
21#include <sys/stat.h>
22#include <sys/types.h>
23#include <unistd.h>
24
25#include <commandutils.hpp>
26#include <cstdint>
27#include <fstream>
28#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
220ipmi_ret_t cmd_mdr2_agent_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
221 ipmi_request_t request,
222 ipmi_response_t response,
223 ipmi_data_len_t data_len,
224 ipmi_context_t context)
225{
226 auto requestData = reinterpret_cast<const MDRiiGetAgentStatus *>(request);
227 auto responseData = reinterpret_cast<MDRiiAgentStatusResponse *>(response);
228
229 if (*data_len != sizeof(MDRiiGetAgentStatus))
230 {
231 *data_len = 0;
232 return IPMI_CC_REQ_DATA_LEN_INVALID;
233 }
234
235 *data_len = 0;
236
237 if (mdrv2 == nullptr)
238 {
239 mdrv2 = std::make_unique<MDRV2>();
240 }
241
242 int agentIndex = mdrv2->agentLookup(requestData->agentId);
243 if (agentIndex == -1)
244 {
245 phosphor::logging::log<phosphor::logging::level::ERR>(
246 "Unknown agent id",
247 phosphor::logging::entry("ID=%x", requestData->agentId));
248 return IPMI_CC_PARM_OUT_OF_RANGE;
249 }
250
251 responseData->mdrVersion = mdr2Version;
252 responseData->agentVersion = smbiosAgentVersion;
253 responseData->dirVersion = mdrv2->smbiosDir.dirVersion;
254 responseData->dirEntries = mdrv2->smbiosDir.dirEntries;
255
256 if (mdrv2->smbiosDir.remoteDirVersion != requestData->dirVersion)
257 {
258 mdrv2->smbiosDir.remoteDirVersion = requestData->dirVersion;
259 responseData->dataRequest =
260 static_cast<uint8_t>(DirDataRequestEnum::dirDataRequested);
261 }
262 else
263 {
264 responseData->dataRequest =
265 static_cast<uint8_t>(DirDataRequestEnum::dirDataNotRequested);
266 }
267
268 *data_len = sizeof(MDRiiAgentStatusResponse);
269
270 return IPMI_CC_OK;
271}
272
273ipmi_ret_t cmd_mdr2_get_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
274 ipmi_request_t request, ipmi_response_t response,
275 ipmi_data_len_t data_len, ipmi_context_t context)
276{
277 auto requestData = reinterpret_cast<const MDRiiGetDirRequest *>(request);
278 auto dataOut = reinterpret_cast<uint8_t *>(response);
279 std::vector<uint8_t> dirInfo;
280
281 if (*data_len != sizeof(MDRiiGetDirRequest))
282 {
283 *data_len = 0;
284 return IPMI_CC_REQ_DATA_LEN_INVALID;
285 }
286
287 *data_len = 0;
288
289 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
290
291 if (mdrv2 == nullptr)
292 {
293 mdrv2 = std::make_unique<MDRV2>();
294 }
295
296 int agentIndex = mdrv2->agentLookup(requestData->agentId);
297 if (agentIndex == -1)
298 {
299 phosphor::logging::log<phosphor::logging::level::ERR>(
300 "Unknown agent id",
301 phosphor::logging::entry("ID=%x", requestData->agentId));
302 return IPMI_CC_PARM_OUT_OF_RANGE;
303 }
304
305 sdbusplus::message::variant<uint8_t> value = 0;
306 if (0 != mdrv2->sdplusMdrv2GetProperty("DirectoryEntries", value, service))
307 {
308 phosphor::logging::log<phosphor::logging::level::ERR>(
309 "Error getting DirEnries");
310 return IPMI_CC_UNSPECIFIED_ERROR;
311 }
312 if (requestData->dirIndex > variant_ns::get<uint8_t>(value))
313 {
314 return IPMI_CC_PARM_OUT_OF_RANGE;
315 }
316
317 sdbusplus::message::message method = bus.new_method_call(
318 service.c_str(), mdrv2Path, mdrv2Interface, "GetDirectoryInformation");
319
320 method.append(requestData->dirIndex);
321
322 try
323 {
324 sdbusplus::message::message reply = bus.call(method);
325 reply.read(dirInfo);
326 }
327 catch (sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
328 InvalidParameter)
329 {
330 phosphor::logging::log<phosphor::logging::level::ERR>(
331 "Error get dir - Invalid parameter");
332 return IPMI_CC_PARM_OUT_OF_RANGE;
333 }
334 catch (sdbusplus::exception_t &)
335 {
336 phosphor::logging::log<phosphor::logging::level::ERR>(
337 "Error get dir",
338 phosphor::logging::entry("SERVICE=%s", service.c_str()),
339 phosphor::logging::entry("PATH=%s", mdrv2Path));
340 return IPMI_CC_RESPONSE_ERROR;
341 }
342
343 if (dirInfo.size() < sizeof(MDRiiGetDirResponse))
344 {
345 phosphor::logging::log<phosphor::logging::level::ERR>(
346 "Error get dir, response length invalid");
347 return IPMI_CC_UNSPECIFIED_ERROR;
348 }
349
350 auto responseData = reinterpret_cast<MDRiiGetDirResponse *>(dirInfo.data());
351
352 *data_len = dirInfo.size();
353
354 if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
355 // than MAX_IPMI_BUFFER
356 {
357 phosphor::logging::log<phosphor::logging::level::ERR>(
358 "Data length send from service is invalid");
359 *data_len = 0;
360 return IPMI_CC_RESPONSE_ERROR;
361 }
362
363 std::copy(&dirInfo[0], &dirInfo[*data_len], dataOut);
364
365 return IPMI_CC_OK;
366}
367
368ipmi_ret_t cmd_mdr2_send_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
369 ipmi_request_t request, ipmi_response_t response,
370 ipmi_data_len_t data_len, ipmi_context_t context)
371{
372 auto requestData = reinterpret_cast<const MDRiiSendDirRequest *>(request);
373 std::vector<uint8_t> idVector;
374 bool teminate = false;
375
376 if (*data_len != sizeof(MDRiiSendDirRequest))
377 {
378 *data_len = 0;
379 return IPMI_CC_REQ_DATA_LEN_INVALID;
380 }
381
382 *data_len = 0;
383
384 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
385
386 if (mdrv2 == nullptr)
387 {
388 mdrv2 = std::make_unique<MDRV2>();
389 }
390
391 int agentIndex = mdrv2->agentLookup(requestData->agentId);
392 if (agentIndex == -1)
393 {
394 phosphor::logging::log<phosphor::logging::level::ERR>(
395 "Unknown agent id",
396 phosphor::logging::entry("ID=%x", requestData->agentId));
397 return IPMI_CC_PARM_OUT_OF_RANGE;
398 }
399
400 if ((requestData->dirIndex + requestData->returnedEntries) > maxDirEntries)
401 {
402 phosphor::logging::log<phosphor::logging::level::ERR>(
403 "Too many directory entries");
404 return IPMI_CC_STORGE_LEAK;
405 }
406
407 sdbusplus::message::message method = bus.new_method_call(
408 service.c_str(), mdrv2Path, mdrv2Interface, "SendDirectoryInformation");
409 method.append(requestData->dirVersion, requestData->dirIndex,
410 requestData->returnedEntries, requestData->remainingEntries);
411 uint8_t *reqPoint;
412 for (int index = 0; index < requestData->returnedEntries; index++)
413 {
414 reqPoint = (uint8_t *)&(requestData->data[index]);
415 std::copy(reqPoint, sizeof(Mdr2DirEntry) + reqPoint, idVector.data());
416 }
417 method.append(idVector);
418
419 try
420 {
421 sdbusplus::message::message reply = bus.call(method);
422 reply.read(teminate);
423 }
424 catch (sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
425 InvalidParameter)
426 {
427 phosphor::logging::log<phosphor::logging::level::ERR>(
428 "Error send dir - Invalid parameter");
429 return IPMI_CC_PARM_OUT_OF_RANGE;
430 }
431 catch (sdbusplus::exception_t &)
432 {
433 phosphor::logging::log<phosphor::logging::level::ERR>(
434 "Error send dir",
435 phosphor::logging::entry("SERVICE=%s", service.c_str()),
436 phosphor::logging::entry("PATH=%s", mdrv2Path));
437 return IPMI_CC_RESPONSE_ERROR;
438 }
439
440 *data_len = 1;
441 if (teminate == false)
442 *(static_cast<uint8_t *>(response)) = 0;
443 else
444 *(static_cast<uint8_t *>(response)) = 1;
445 return IPMI_CC_OK;
446}
447
448ipmi_ret_t cmd_mdr2_get_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
449 ipmi_request_t request,
450 ipmi_response_t response,
451 ipmi_data_len_t data_len,
452 ipmi_context_t context)
453{
454 auto requestData =
455 reinterpret_cast<const MDRiiGetDataInfoRequest *>(request);
456 auto dataOut = reinterpret_cast<uint8_t *>(response);
457 std::vector<uint8_t> res;
458
459 if (*data_len < sizeof(MDRiiGetDataInfoRequest))
460 {
461 *data_len = 0;
462 return IPMI_CC_REQ_DATA_LEN_INVALID;
463 }
464
465 *data_len = 0;
466
467 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
468
469 if (mdrv2 == nullptr)
470 {
471 mdrv2 = std::make_unique<MDRV2>();
472 }
473
474 int agentIndex = mdrv2->agentLookup(requestData->agentId);
475 if (agentIndex == -1)
476 {
477 phosphor::logging::log<phosphor::logging::level::ERR>(
478 "Unknown agent id",
479 phosphor::logging::entry("ID=%x", requestData->agentId));
480 return IPMI_CC_PARM_OUT_OF_RANGE;
481 }
482
483 int idIndex =
484 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
485 sizeof(requestData->dataSetInfo.dataInfo), service);
486
487 if ((idIndex < 0) || (idIndex >= maxDirEntries))
488 {
489 phosphor::logging::log<phosphor::logging::level::ERR>(
490 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
491 return IPMI_CC_PARM_OUT_OF_RANGE;
492 }
493
494 sdbusplus::message::message method = bus.new_method_call(
495 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataInformation");
496
497 method.append(idIndex);
498
499 try
500 {
501 sdbusplus::message::message reply = bus.call(method);
502 reply.read(res);
503 }
504 catch (sdbusplus::exception_t &)
505 {
506 phosphor::logging::log<phosphor::logging::level::ERR>(
507 "Error get data info",
508 phosphor::logging::entry("SERVICE=%s", service.c_str()),
509 phosphor::logging::entry("PATH=%s", mdrv2Path));
510 return IPMI_CC_RESPONSE_ERROR;
511 }
512
513 if (res.size() != sizeof(MDRiiGetDataInfoResponse))
514 {
515 phosphor::logging::log<phosphor::logging::level::ERR>(
516 "Get data info response length not invalid");
517 return IPMI_CC_UNSPECIFIED_ERROR;
518 }
519 *data_len = static_cast<size_t>(res.size());
520 std::copy(&res[0], &res[*data_len], dataOut);
521
522 return IPMI_CC_OK;
523}
524
525// Offer a agent ID to get the "Data Set ID"
526ipmi_ret_t cmd_mdr2_data_info_offer(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
527 ipmi_request_t request,
528 ipmi_response_t response,
529 ipmi_data_len_t data_len,
530 ipmi_context_t context)
531{
532 auto requestData = reinterpret_cast<const MDRiiOfferDataInfo *>(request);
533 auto dataOut = reinterpret_cast<uint8_t *>(response);
534 std::vector<uint8_t> dataInfo;
535
536 if (*data_len != sizeof(MDRiiOfferDataInfo))
537 {
538 *data_len = 0;
539 return IPMI_CC_REQ_DATA_LEN_INVALID;
540 }
541
542 *data_len = 0;
543
544 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
545
546 if (mdrv2 == nullptr)
547 {
548 mdrv2 = std::make_unique<MDRV2>();
549 }
550
551 int agentIndex = mdrv2->agentLookup(requestData->agentId);
552 if (agentIndex == -1)
553 {
554 phosphor::logging::log<phosphor::logging::level::ERR>(
555 "Unknown agent id",
556 phosphor::logging::entry("ID=%x", requestData->agentId));
557 return IPMI_CC_PARM_OUT_OF_RANGE;
558 }
559
560 sdbusplus::message::message method = bus.new_method_call(
561 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataOffer");
562
563 try
564 {
565 sdbusplus::message::message reply = bus.call(method);
566 reply.read(dataInfo);
567 }
568 catch (
569 sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::UpdateInProgress
570 &)
571 {
572 phosphor::logging::log<phosphor::logging::level::ERR>(
573 "Send data info offer failed - not available to update data "
574 "into agent at present");
575 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
576 }
577 catch (sdbusplus::exception_t &)
578 {
579 phosphor::logging::log<phosphor::logging::level::ERR>(
580 "Error send data info offer",
581 phosphor::logging::entry("SERVICE=%s", service.c_str()),
582 phosphor::logging::entry("PATH=%s", mdrv2Path));
583 return IPMI_CC_RESPONSE_ERROR;
584 }
585
586 if (dataInfo.size() != sizeof(MDRiiOfferDataInfoResponse))
587 {
588 phosphor::logging::log<phosphor::logging::level::ERR>(
589 "Error send data info offer, return length invalid");
590 return IPMI_CC_UNSPECIFIED_ERROR;
591 }
592
593 *data_len = dataInfo.size();
594 std::copy(dataInfo.begin(), dataInfo.end(), dataOut);
595 return IPMI_CC_OK;
596}
597
598ipmi_ret_t cmd_mdr2_send_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
599 ipmi_request_t request,
600 ipmi_response_t response,
601 ipmi_data_len_t data_len,
602 ipmi_context_t context)
603{
604 auto requestData =
605 reinterpret_cast<const MDRiiSendDataInfoRequest *>(request);
606 bool entryChanged = true;
607
608 if (*data_len != sizeof(MDRiiSendDataInfoRequest))
609 {
610 *data_len = 0;
611 return IPMI_CC_REQ_DATA_LEN_INVALID;
612 }
613
614 *data_len = 0;
615
616 if (requestData->dataLength > smbiosTableStorageSize)
617 {
618 phosphor::logging::log<phosphor::logging::level::ERR>(
619 "Requested data length is out of SMBIOS Table storage size.");
620 return IPMI_CC_PARM_OUT_OF_RANGE;
621 }
622
623 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
624
625 if (mdrv2 == nullptr)
626 {
627 mdrv2 = std::make_unique<MDRV2>();
628 }
629
630 int agentIndex = mdrv2->agentLookup(requestData->agentId);
631 if (agentIndex == -1)
632 {
633 phosphor::logging::log<phosphor::logging::level::ERR>(
634 "Unknown agent id",
635 phosphor::logging::entry("ID=%x", requestData->agentId));
636 return IPMI_CC_PARM_OUT_OF_RANGE;
637 }
638
639 int idIndex =
640 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
641 sizeof(requestData->dataSetInfo.dataInfo), service);
642
643 if ((idIndex < 0) || (idIndex >= maxDirEntries))
644 {
645 phosphor::logging::log<phosphor::logging::level::ERR>(
646 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
647 return IPMI_CC_PARM_OUT_OF_RANGE;
648 }
649
650 sdbusplus::message::message method = bus.new_method_call(
651 service.c_str(), mdrv2Path, mdrv2Interface, "SendDataInformation");
652
653 method.append((uint8_t)idIndex, requestData->validFlag,
654 requestData->dataLength, requestData->dataVersion,
655 requestData->timeStamp);
656
657 try
658 {
659 sdbusplus::message::message reply = bus.call(method);
660 reply.read(entryChanged);
661 }
662 catch (sdbusplus::exception_t &)
663 {
664 phosphor::logging::log<phosphor::logging::level::ERR>(
665 "Error send data info",
666 phosphor::logging::entry("SERVICE=%s", service.c_str()),
667 phosphor::logging::entry("PATH=%s", mdrv2Path));
668 return IPMI_CC_RESPONSE_ERROR;
669 }
670
671 *data_len = 1;
672
673 if (entryChanged)
674 {
675 *(static_cast<uint8_t *>(response)) = 1;
676 }
677 else
678 {
679 *(static_cast<uint8_t *>(response)) = 0;
680 }
681
682 return IPMI_CC_OK;
683}
684
685ipmi_ret_t cmd_mdr2_get_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
686 ipmi_request_t request,
687 ipmi_response_t response,
688 ipmi_data_len_t data_len,
689 ipmi_context_t context)
690{
691 auto requestData =
692 reinterpret_cast<const MDRiiGetDataBlockRequest *>(request);
693 auto responseData = reinterpret_cast<MDRiiGetDataBlockResponse *>(response);
694 std::tuple<uint8_t, uint32_t, uint32_t, std::vector<uint8_t>> res;
695 std::vector<uint8_t> resData;
696 uint8_t status = 1;
697
698 if (*data_len != sizeof(MDRiiGetDataBlockRequest))
699 {
700 *data_len = 0;
701 return IPMI_CC_REQ_DATA_LEN_INVALID;
702 }
703
704 *data_len = 0;
705
706 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
707
708 if (mdrv2 == nullptr)
709 {
710 mdrv2 = std::make_unique<MDRV2>();
711 }
712
713 int agentIndex = mdrv2->agentLookup(requestData->agentId);
714 if (agentIndex == -1)
715 {
716 phosphor::logging::log<phosphor::logging::level::ERR>(
717 "Unknown agent id",
718 phosphor::logging::entry("ID=%x", requestData->agentId));
719 return IPMI_CC_PARM_OUT_OF_RANGE;
720 }
721
722 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
723
724 if ((idIndex < 0) || (idIndex >= maxDirEntries))
725 {
726 phosphor::logging::log<phosphor::logging::level::ERR>(
727 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
728 return IPMI_CC_PARM_OUT_OF_RANGE;
729 }
730
731 if (requestData->xferOffset >= mdrv2->smbiosDir.dir[idIndex].common.size)
732 {
733 phosphor::logging::log<phosphor::logging::level::ERR>(
734 "Offset is outside of range.");
735 return IPMI_CC_PARM_OUT_OF_RANGE;
736 }
737
738 size_t outSize =
739 (requestData->xferLength > mdrv2->smbiosDir.dir[idIndex].xferSize)
740 ? mdrv2->smbiosDir.dir[idIndex].xferSize
741 : requestData->xferLength;
742 if (outSize > UINT_MAX - requestData->xferOffset)
743 {
744 phosphor::logging::log<phosphor::logging::level::ERR>(
745 "Out size and offset are out of range");
746 return IPMI_CC_PARM_OUT_OF_RANGE;
747 }
748 if ((requestData->xferOffset + outSize) >
749 mdrv2->smbiosDir.dir[idIndex].common.size)
750 {
751 outSize =
752 mdrv2->smbiosDir.dir[idIndex].common.size - requestData->xferOffset;
753 }
754
755 responseData->xferLength = outSize;
756 if (responseData->xferLength > requestData->xferLength)
757 {
758 phosphor::logging::log<phosphor::logging::level::ERR>(
759 "Get data block unexpected error.");
760 return IPMI_CC_UNSPECIFIED_ERROR;
761 }
762
763 if ((requestData->xferOffset + outSize) >
764 UINT_MAX -
765 reinterpret_cast<size_t>(mdrv2->smbiosDir.dir[idIndex].dataStorage))
766 {
767 phosphor::logging::log<phosphor::logging::level::ERR>(
768 "Input data to calculate checksum is out of range");
769 return IPMI_CC_PARM_OUT_OF_RANGE;
770 }
771
772 uint32_t u32Checksum = mdrv2->calcChecksum32(
773 mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset,
774 outSize);
775 if (u32Checksum == invalidChecksum)
776 {
777 phosphor::logging::log<phosphor::logging::level::ERR>(
778 "Get data block failed - invalid checksum");
779 return IPMI_CC_OEM_INVALID_CHECKSUM;
780 }
781 responseData->checksum = u32Checksum;
782
783 *data_len = sizeof(responseData->xferLength) +
784 sizeof(responseData->checksum) + outSize;
785
786 if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
787 // than MAX_IPMI_BUFFER
788 {
789 phosphor::logging::log<phosphor::logging::level::ERR>(
790 "Data length send from service is invalid");
791 *data_len = 0;
792 return IPMI_CC_RESPONSE_ERROR;
793 }
794
795 std::copy(
796 &mdrv2->smbiosDir.dir[idIndex].dataStorage[requestData->xferOffset],
797 &mdrv2->smbiosDir.dir[idIndex]
798 .dataStorage[requestData->xferOffset + outSize],
799 responseData->data);
800
801 return IPMI_CC_OK;
802}
803
804ipmi_ret_t cmd_mdr2_send_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
805 ipmi_request_t request,
806 ipmi_response_t response,
807 ipmi_data_len_t data_len,
808 ipmi_context_t context)
809{
810 auto requestData =
811 reinterpret_cast<const MDRiiSendDataBlockRequest *>(request);
812
813 if (*data_len != sizeof(MDRiiSendDataBlockRequest))
814 {
815 *data_len = 0;
816 return IPMI_CC_REQ_DATA_LEN_INVALID;
817 }
818
819 *data_len = 0;
820
821 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
822
823 if (mdrv2 == nullptr)
824 {
825 mdrv2 = std::make_unique<MDRV2>();
826 }
827
828 int agentIndex = mdrv2->agentLookup(requestData->agentId);
829 if (agentIndex == -1)
830 {
831 phosphor::logging::log<phosphor::logging::level::ERR>(
832 "Unknown agent id",
833 phosphor::logging::entry("ID=%x", requestData->agentId));
834 return IPMI_CC_PARM_OUT_OF_RANGE;
835 }
836
837 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
838
839 if ((idIndex < 0) || (idIndex >= maxDirEntries))
840 {
841 phosphor::logging::log<phosphor::logging::level::ERR>(
842 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
843 return IPMI_CC_PARM_OUT_OF_RANGE;
844 }
845
846 if (mdrv2->smbiosIsUpdating(idIndex))
847 {
848 if (requestData->xferOffset > UINT_MAX - requestData->xferLength)
849 {
850 phosphor::logging::log<phosphor::logging::level::ERR>(
851 "Offset and length are out of range");
852 return IPMI_CC_PARM_OUT_OF_RANGE;
853 }
854 if (((requestData->xferOffset + requestData->xferLength) >
855 mdrv2->smbiosDir.dir[idIndex].maxDataSize) ||
856 ((requestData->xferOffset + requestData->xferLength) >
857 mdrv2->smbiosDir.dir[idIndex].common.dataSetSize))
858 {
859 phosphor::logging::log<phosphor::logging::level::ERR>(
860 "Send data block Invalid offset/length");
861 return IPMI_CC_REQUEST_DATA_FIELD_LENGTH_LIMIT_EXCEEDED;
862 }
863 if (reinterpret_cast<size_t>(
864 mdrv2->smbiosDir.dir[idIndex].dataStorage) >
865 UINT_MAX - requestData->xferOffset)
866 {
867 phosphor::logging::log<phosphor::logging::level::ERR>(
868 "Offset is out of range");
869 return IPMI_CC_PARM_OUT_OF_RANGE;
870 }
871 uint8_t *destAddr =
872 mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset;
873 uint8_t *sourceAddr = reinterpret_cast<uint8_t *>(mdrv2->area->vPtr);
874 uint32_t calcChecksum =
875 mdrv2->calcChecksum32(sourceAddr, requestData->xferLength);
876 if (calcChecksum != requestData->checksum)
877 {
878 phosphor::logging::log<phosphor::logging::level::ERR>(
879 "Send data block Invalid checksum");
880 return IPMI_CC_OEM_INVALID_CHECKSUM;
881 }
882 else
883 {
884 if (reinterpret_cast<size_t>(sourceAddr) >
885 UINT_MAX - requestData->xferLength)
886 {
887 phosphor::logging::log<phosphor::logging::level::ERR>(
888 "Length is out of range");
889 return IPMI_CC_PARM_OUT_OF_RANGE;
890 }
891 std::copy(sourceAddr, sourceAddr + requestData->xferLength,
892 destAddr);
893 }
894 }
895 else
896 {
897 phosphor::logging::log<phosphor::logging::level::ERR>(
898 "Send data block failed, other data is updating");
899 return IPMI_CC_DESTINATION_UNAVAILABLE;
900 }
901
902 return IPMI_CC_OK;
903}
904
905bool MDRV2::storeDatatoFlash(MDRSMBIOSHeader *mdrHdr, uint8_t *data)
906{
907 std::ofstream smbiosFile(mdrType2File,
908 std::ios_base::binary | std::ios_base::trunc);
909 if (!smbiosFile.good())
910 {
911 phosphor::logging::log<phosphor::logging::level::ERR>(
912 "Write data from flash error - Open MDRV2 table file failure");
913 return false;
914 }
915
916 try
917 {
918 smbiosFile.write(reinterpret_cast<char *>(mdrHdr),
919 sizeof(MDRSMBIOSHeader));
920 smbiosFile.write(reinterpret_cast<char *>(data), mdrHdr->dataSize);
921 }
922 catch (std::ofstream::failure &e)
923 {
924 phosphor::logging::log<phosphor::logging::level::ERR>(
925 "Write data from flash error - write data error");
926 return false;
927 }
928
929 return true;
930}
931
932void SharedMemoryArea::Initialize(uint32_t addr, uint32_t areaSize)
933{
934 int memDriver = 0;
935
936 // open mem driver for the system memory access
937 memDriver = open("/dev/vgasharedmem", O_RDONLY);
938 if (memDriver < 0)
939 {
940 phosphor::logging::log<phosphor::logging::level::ERR>(
941 "Cannot access mem driver");
942 throw std::system_error(EIO, std::generic_category());
943 }
944
945 // map the system memory
946 vPtr = mmap(NULL, // where to map to: don't mind
947 areaSize, // how many bytes ?
948 PROT_READ, // want to read and write
949 MAP_SHARED, // no copy on write
950 memDriver, // handle to /dev/mem
951 (physicalAddr & pageMask)); // hopefully the Text-buffer :-)
952
953 close(memDriver);
954 if (vPtr == MAP_FAILED)
955 {
956 phosphor::logging::log<phosphor::logging::level::ERR>(
957 "Failed to map share memory");
958 throw std::system_error(EIO, std::generic_category());
959 }
960 size = areaSize;
961 physicalAddr = addr;
962}
963
964bool MDRV2::smbiosUnlock(uint8_t index)
965{
966 bool ret;
967 switch (smbiosDir.dir[index].stage)
968 {
969 case MDR2SMBIOSStatusEnum::mdr2Updating:
970 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updated;
971 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
972
973 timer->stop();
974 smbiosDir.dir[index].lockHandle = 0;
975 ret = true;
976 break;
977
978 case MDR2SMBIOSStatusEnum::mdr2Updated:
979 case MDR2SMBIOSStatusEnum::mdr2Loaded:
980 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
981
982 timer->stop();
983
984 smbiosDir.dir[index].lockHandle = 0;
985 ret = true;
986 break;
987
988 default:
989 break;
990 }
991
992 return ret;
993}
994
995bool MDRV2::smbiosTryLock(uint8_t flag, uint8_t index, uint16_t *session,
996 uint16_t timeout)
997{
998 bool ret = false;
999 uint32_t u32Status = 0;
1000
1001 if (timeout == 0)
1002 {
1003 timeout = defaultTimeout;
1004 }
1005 std::chrono::microseconds usec(timeout * sysClock);
1006
1007 switch (smbiosDir.dir[index].stage)
1008 {
1009 case MDR2SMBIOSStatusEnum::mdr2Updating:
1010 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
1011 {
1012 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
1013 timer->start(usec);
1014 lockIndex = index;
1015
1016 *session = getSessionHandle(&smbiosDir);
1017 smbiosDir.dir[index].lockHandle = *session;
1018 ret = true;
1019 }
1020 break;
1021 case MDR2SMBIOSStatusEnum::mdr2Init:
1022 if (flag)
1023 {
1024 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updating;
1025 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
1026 timer->start(usec);
1027 lockIndex = index;
1028
1029 *session = getSessionHandle(&smbiosDir);
1030 smbiosDir.dir[index].lockHandle = *session;
1031 ret = true;
1032 }
1033 break;
1034
1035 case MDR2SMBIOSStatusEnum::mdr2Updated:
1036 case MDR2SMBIOSStatusEnum::mdr2Loaded:
1037 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
1038 {
1039 if (flag)
1040 {
1041 smbiosDir.dir[index].stage =
1042 MDR2SMBIOSStatusEnum::mdr2Updating;
1043 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
1044 }
1045 else
1046 {
1047 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
1048 }
1049
1050 timer->start(usec);
1051 lockIndex = index;
1052
1053 *session = getSessionHandle(&smbiosDir);
1054 smbiosDir.dir[index].lockHandle = *session;
1055 ret = true;
1056 }
1057 break;
1058
1059 default:
1060 break;
1061 }
1062 return ret;
1063}
1064
1065void MDRV2::timeoutHandler()
1066{
1067 smbiosUnlock(lockIndex);
1068 mdrv2->area.reset(nullptr);
1069}
1070
1071ipmi_ret_t cmd_mdr2_lock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1072 ipmi_request_t request, ipmi_response_t response,
1073 ipmi_data_len_t data_len, ipmi_context_t context)
1074{
1075 auto requestData = reinterpret_cast<const MDRiiLockDataRequest *>(request);
1076 auto responseData = reinterpret_cast<MDRiiLockDataResponse *>(response);
1077 uint16_t session = 0;
1078
1079 std::tuple<bool, uint8_t, uint16_t, uint32_t, uint32_t, uint32_t> res;
1080
1081 if (*data_len < sizeof(MDRiiLockDataRequest))
1082 {
1083 *data_len = 0;
1084 return IPMI_CC_REQ_DATA_LEN_INVALID;
1085 }
1086
1087 *data_len = 0;
1088
1089 if (mdrv2 == nullptr)
1090 {
1091 mdrv2 = std::make_unique<MDRV2>();
1092 }
1093
1094 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1095 if (agentIndex == -1)
1096 {
1097 phosphor::logging::log<phosphor::logging::level::ERR>(
1098 "Unknown agent id",
1099 phosphor::logging::entry("ID=%x", requestData->agentId));
1100 return IPMI_CC_PARM_OUT_OF_RANGE;
1101 }
1102
1103 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1104
1105 int idIndex =
1106 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
1107 sizeof(requestData->dataSetInfo.dataInfo), service);
1108
1109 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1110 {
1111 phosphor::logging::log<phosphor::logging::level::ERR>(
1112 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1113 return IPMI_CC_PARM_OUT_OF_RANGE;
1114 }
1115
1116 if (!mdrv2->smbiosTryLock(0, idIndex, &session, requestData->timeout))
1117 {
1118 phosphor::logging::log<phosphor::logging::level::ERR>(
1119 "Lock Data failed - cannot lock idIndex");
1120 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
1121 }
1122
1123 *data_len = sizeof(MDRiiLockDataResponse);
1124
1125 responseData->mdrVersion = mdr2Version;
1126 responseData->lockHandle = session;
1127 responseData->dataLength = mdrv2->smbiosDir.dir[idIndex].common.size;
1128 responseData->xferAddress = mdrv2->smbiosDir.dir[idIndex].xferBuff;
1129 responseData->xferLength = mdrv2->smbiosDir.dir[idIndex].xferSize;
1130
1131 return IPMI_CC_OK;
1132}
1133
1134ipmi_ret_t cmd_mdr2_unlock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1135 ipmi_request_t request,
1136 ipmi_response_t response,
1137 ipmi_data_len_t data_len,
1138 ipmi_context_t context)
1139{
1140 phosphor::logging::log<phosphor::logging::level::ERR>("unlock data");
1141 auto requestData =
1142 reinterpret_cast<const MDRiiUnlockDataRequest *>(request);
1143
1144 if (*data_len != sizeof(MDRiiUnlockDataRequest))
1145 {
1146 *data_len = 0;
1147 return IPMI_CC_REQ_DATA_LEN_INVALID;
1148 }
1149
1150 *data_len = 0;
1151
1152 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1153
1154 if (mdrv2 == nullptr)
1155 {
1156 mdrv2 = std::make_unique<MDRV2>();
1157 }
1158
1159 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1160 if (agentIndex == -1)
1161 {
1162 phosphor::logging::log<phosphor::logging::level::ERR>(
1163 "Unknown agent id",
1164 phosphor::logging::entry("ID=%x", requestData->agentId));
1165 return IPMI_CC_PARM_OUT_OF_RANGE;
1166 }
1167
1168 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
1169
1170 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1171 {
1172 phosphor::logging::log<phosphor::logging::level::ERR>(
1173 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1174 return IPMI_CC_PARM_OUT_OF_RANGE;
1175 }
1176
1177 if (!mdrv2->smbiosUnlock(idIndex))
1178 {
1179 phosphor::logging::log<phosphor::logging::level::ERR>(
1180 "Unlock Data failed - cannot unlock idIndex");
1181 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
1182 }
1183
1184 return IPMI_CC_OK;
1185}
1186
1187ipmi_ret_t cmd_mdr2_data_start(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1188 ipmi_request_t request, ipmi_response_t response,
1189 ipmi_data_len_t data_len, ipmi_context_t context)
1190{
1191 auto requestData = reinterpret_cast<const MDRiiDataStartRequest *>(request);
1192 auto responseData = reinterpret_cast<MDRiiDataStartResponse *>(response);
1193 std::vector<uint8_t> idVector;
1194 uint16_t session = 0;
1195
1196 if (*data_len != sizeof(MDRiiDataStartRequest))
1197 {
1198 *data_len = 0;
1199 return IPMI_CC_REQ_DATA_LEN_INVALID;
1200 }
1201
1202 *data_len = 0;
1203
1204 if (requestData->dataLength > smbiosTableStorageSize)
1205 {
1206 phosphor::logging::log<phosphor::logging::level::ERR>(
1207 "Requested data length is out of SMBIOS Table storage size.");
1208 return IPMI_CC_PARM_OUT_OF_RANGE;
1209 }
1210
1211 if ((requestData->xferLength + requestData->xferAddress) > mdriiSMSize)
1212 {
1213 phosphor::logging::log<phosphor::logging::level::ERR>(
1214 "Invalid data address and size");
1215 return IPMI_CC_PARM_OUT_OF_RANGE;
1216 }
1217
1218 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1219
1220 if (mdrv2 == nullptr)
1221 {
1222 mdrv2 = std::make_unique<MDRV2>();
1223 }
1224
1225 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1226 if (agentIndex == -1)
1227 {
1228 phosphor::logging::log<phosphor::logging::level::ERR>(
1229 "Unknown agent id",
1230 phosphor::logging::entry("ID=%x", requestData->agentId));
1231 return IPMI_CC_PARM_OUT_OF_RANGE;
1232 }
1233
1234 int idIndex =
1235 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
1236 sizeof(requestData->dataSetInfo.dataInfo), service);
1237
1238 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1239 {
1240 phosphor::logging::log<phosphor::logging::level::ERR>(
1241 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1242 return IPMI_CC_PARM_OUT_OF_RANGE;
1243 }
1244
1245 if (mdrv2->smbiosTryLock(1, idIndex, &session, requestData->timeout))
1246 {
1247 try
1248 {
1249 mdrv2->area = std::make_unique<SharedMemoryArea>(
1250 requestData->xferAddress, requestData->xferLength);
1251 }
1252 catch (const std::system_error &e)
1253 {
1254 mdrv2->smbiosUnlock(idIndex);
1255 phosphor::logging::log<phosphor::logging::level::ERR>(
1256 "Unable to access share memory");
1257 return IPMI_CC_UNSPECIFIED_ERROR;
1258 }
1259 mdrv2->smbiosDir.dir[idIndex].common.size = requestData->dataLength;
1260 mdrv2->smbiosDir.dir[idIndex].lockHandle = session;
1261 if (-1 ==
1262 mdrv2->syncDirCommonData(
1263 idIndex, mdrv2->smbiosDir.dir[idIndex].common.size, service))
1264 {
1265 phosphor::logging::log<phosphor::logging::level::ERR>(
1266 "Unable to sync data to service");
1267 return IPMI_CC_RESPONSE_ERROR;
1268 }
1269 }
1270 else
1271 {
1272 phosphor::logging::log<phosphor::logging::level::ERR>(
1273 "Canot lock smbios");
1274 return IPMI_CC_UNSPECIFIED_ERROR;
1275 }
1276
1277 responseData->sessionHandle = session;
1278 responseData->xferStartAck = 1;
1279
1280 *data_len = sizeof(MDRiiDataStartResponse);
1281 return IPMI_CC_OK;
1282}
1283
1284ipmi_ret_t cmd_mdr2_data_done(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1285 ipmi_request_t request, ipmi_response_t response,
1286 ipmi_data_len_t data_len, ipmi_context_t context)
1287{
1288 auto requestData = reinterpret_cast<const MDRiiDataDoneRequest *>(request);
1289
1290 if (*data_len != sizeof(MDRiiDataDoneRequest))
1291 {
1292 *data_len = 0;
1293 return IPMI_CC_REQ_DATA_LEN_INVALID;
1294 }
1295
1296 *data_len = 0;
1297
1298 if (mdrv2 == nullptr)
1299 {
1300 mdrv2 = std::make_unique<MDRV2>();
1301 }
1302
1303 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1304 if (agentIndex == -1)
1305 {
1306 phosphor::logging::log<phosphor::logging::level::ERR>(
1307 "Unknown agent id",
1308 phosphor::logging::entry("ID=%x", requestData->agentId));
1309 return IPMI_CC_PARM_OUT_OF_RANGE;
1310 }
1311
1312 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
1313
1314 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1315 {
1316 phosphor::logging::log<phosphor::logging::level::ERR>(
1317 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1318 return IPMI_CC_PARM_OUT_OF_RANGE;
1319 }
1320
1321 if (!mdrv2->smbiosUnlock(idIndex))
1322 {
1323 phosphor::logging::log<phosphor::logging::level::ERR>(
1324 "Send data done failed - cannot unlock idIndex");
1325 return IPMI_CC_DESTINATION_UNAVAILABLE;
1326 }
1327
1328 mdrv2->area.reset(nullptr);
1329 MDRSMBIOSHeader mdr2Smbios;
1330 mdr2Smbios.mdrType = mdrTypeII;
1331 mdr2Smbios.dirVer = mdrv2->smbiosDir.dir[0].common.dataVersion;
1332 mdr2Smbios.timestamp = mdrv2->smbiosDir.dir[0].common.timestamp;
1333 mdr2Smbios.dataSize = mdrv2->smbiosDir.dir[0].common.size;
1334
1335 if (access(smbiosPath, 0) == -1)
1336 {
1337 int flag = mkdir(smbiosPath, S_IRWXU);
1338 if (flag != 0)
1339 {
1340 phosphor::logging::log<phosphor::logging::level::ERR>(
1341 "create folder failed for writting smbios file");
1342 }
1343 }
1344 if (!mdrv2->storeDatatoFlash(
1345 &mdr2Smbios, mdrv2->smbiosDir.dir[smbiosDirIndex].dataStorage))
1346 {
1347 phosphor::logging::log<phosphor::logging::level::ERR>(
1348 "MDR2 Store data to flash failed");
1349 return IPMI_CC_DESTINATION_UNAVAILABLE;
1350 }
1351
1352 bool status = false;
1353 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1354 sdbusplus::message::message method = bus.new_method_call(
1355 service.c_str(), mdrv2Path, mdrv2Interface, "AgentSynchronizeData");
1356
1357 try
1358 {
1359 sdbusplus::message::message reply = bus.call(method);
1360 reply.read(status);
1361 }
1362 catch (sdbusplus::exception_t &)
1363 {
1364 phosphor::logging::log<phosphor::logging::level::ERR>(
1365 "Error Sync data with service",
1366 phosphor::logging::entry("SERVICE=%s", service.c_str()),
1367 phosphor::logging::entry("PATH=%s", mdrv2Path));
1368 return IPMI_CC_RESPONSE_ERROR;
1369 }
1370
1371 if (!status)
1372 {
1373 phosphor::logging::log<phosphor::logging::level::ERR>(
1374 "Sync data with service failure");
1375 return IPMI_CC_UNSPECIFIED_ERROR;
1376 }
1377
1378 return IPMI_CC_OK;
1379}
1380
1381static void register_netfn_smbiosmdrv2_functions(void)
1382{
1383 // MDR V2 Command
1384 // <Get MDRII Status Command>
1385 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1386 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_AGENT_STATUS,
1387 NULL, cmd_mdr2_agent_status, PRIVILEGE_OPERATOR);
1388
1389 // <Get MDRII Directory Command>
1390 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1391 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DIR, NULL,
1392 cmd_mdr2_get_dir, PRIVILEGE_OPERATOR);
1393
1394 // <Send MDRII Directory Command>
1395 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1396 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DIR, NULL,
1397 cmd_mdr2_send_dir, PRIVILEGE_OPERATOR);
1398
1399 // <Get MDRII Data Info Command>
1400 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1401 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_INFO,
1402 NULL, cmd_mdr2_get_data_info, PRIVILEGE_OPERATOR);
1403
1404 // <Send MDRII Info Offer>
1405 ipmi_register_callback(
1406 NETFUN_INTEL_APP_OEM,
1407 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO_OFFER, NULL,
1408 cmd_mdr2_data_info_offer, PRIVILEGE_OPERATOR);
1409
1410 // <Send MDRII Data Info>
1411 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1412 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO,
1413 NULL, cmd_mdr2_send_data_info, PRIVILEGE_OPERATOR);
1414
1415 // <Get MDRII Data Block Command>
1416 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1417 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_BLOCK,
1418 NULL, cmd_mdr2_get_data_block, PRIVILEGE_OPERATOR);
1419
1420 // <Send MDRII Data Block>
1421 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1422 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_BLOCK,
1423 NULL, cmd_mdr2_send_data_block, PRIVILEGE_OPERATOR);
1424
1425 // <Lock MDRII Data Command>
1426 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1427 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_LOCK_DATA, NULL,
1428 cmd_mdr2_lock_data, PRIVILEGE_OPERATOR);
1429
1430 // <Unlock MDRII Data Command>
1431 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1432 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_UNLOCK_DATA,
1433 NULL, cmd_mdr2_unlock_data, PRIVILEGE_OPERATOR);
1434
1435 // <Send MDRII Data Start>
1436 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1437 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_START, NULL,
1438 cmd_mdr2_data_start, PRIVILEGE_OPERATOR);
1439
1440 // <Send MDRII Data Done>
1441 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1442 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_DONE, NULL,
1443 cmd_mdr2_data_done, PRIVILEGE_OPERATOR);
1444}