blob: f3c4275e8a3b41587716edd22dc8ab2a09da2a0d [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>
Vernon Mauerya3702c12019-05-22 13:20:59 -070036
37std::unique_ptr<MDRV2> mdrv2 = nullptr;
38
Vernon Mauerya3702c12019-05-22 13:20:59 -070039static void register_netfn_smbiosmdrv2_functions() __attribute__((constructor));
40static sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
41
42int MDRV2::agentLookup(const uint16_t &agentId)
43{
44 int agentIndex = -1;
45
46 if (lastAgentId == agentId)
47 {
48 return lastAgentIndex;
49 }
50
51 if (agentId == smbiosAgentId)
52 {
53 return firstAgentIndex;
54 }
55
56 return agentIndex;
57}
58
59int MDRV2::sdplusMdrv2GetProperty(const std::string &name,
60 sdbusplus::message::variant<uint8_t> &value,
61 const std::string &service)
62{
63 sdbusplus::message::message method =
64 bus.new_method_call(service.c_str(), mdrv2Path, dbusProperties, "Get");
65 method.append(mdrv2Interface, name);
66
67 sdbusplus::message::message reply = bus.call(method);
68
69 try
70 {
71 sdbusplus::message::message reply = bus.call(method);
72 reply.read(value);
73 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -070074 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -070075 {
76 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -070077 "Error get property, sdbusplus call failed",
78 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -070079 return -1;
80 }
81
82 return 0;
83}
84
85int MDRV2::syncDirCommonData(uint8_t idIndex, uint32_t size,
86 const std::string &service)
87{
88 std::vector<uint32_t> commonData;
89 sdbusplus::message::message method =
90 bus.new_method_call(service.c_str(), mdrv2Path, mdrv2Interface,
91 "SynchronizeDirectoryCommonData");
92 method.append(idIndex, size);
93
94 try
95 {
96 sdbusplus::message::message reply = bus.call(method);
97 reply.read(commonData);
98 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -070099 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700100 {
101 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700102 "Error sync dir common data with service",
103 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -0700104 return -1;
105 }
106
107 if (commonData.size() < syncDirCommonSize)
108 {
109 phosphor::logging::log<phosphor::logging::level::ERR>(
110 "Error sync dir common data - data length invalid");
111 return -1;
112 }
113 smbiosDir.dir[idIndex].common.dataSetSize = commonData.at(0);
114 smbiosDir.dir[idIndex].common.dataVersion = commonData.at(1);
115 smbiosDir.dir[idIndex].common.timestamp = commonData.at(2);
116
117 return 0;
118}
119
120int MDRV2::findDataId(const uint8_t *dataInfo, const size_t &len,
121 const std::string &service)
122{
123 int idIndex = -1;
124
125 if (dataInfo == nullptr)
126 {
127 phosphor::logging::log<phosphor::logging::level::ERR>(
128 "Error dataInfo, input is null point");
129 return -1;
130 }
131
132 sdbusplus::message::message method = bus.new_method_call(
133 service.c_str(), mdrv2Path, mdrv2Interface, "FindIdIndex");
134 std::vector<uint8_t> info;
135 info.resize(len);
136 std::copy(dataInfo, dataInfo + len, info.data());
137 method.append(info);
138
139 try
140 {
141 sdbusplus::message::message reply = bus.call(method);
142 reply.read(idIndex);
143 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700144 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700145 {
146 phosphor::logging::log<phosphor::logging::level::ERR>(
147 "Error find id index",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700148 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700149 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 }
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700308 if (requestData->dirIndex > std::get<uint8_t>(value))
Vernon Mauerya3702c12019-05-22 13:20:59 -0700309 {
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 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700323 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700324 {
325 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700326 "Error get dir", phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700327 phosphor::logging::entry("SERVICE=%s", service.c_str()),
328 phosphor::logging::entry("PATH=%s", mdrv2Path));
329 return IPMI_CC_RESPONSE_ERROR;
330 }
331
332 if (dirInfo.size() < sizeof(MDRiiGetDirResponse))
333 {
334 phosphor::logging::log<phosphor::logging::level::ERR>(
335 "Error get dir, response length invalid");
336 return IPMI_CC_UNSPECIFIED_ERROR;
337 }
338
339 auto responseData = reinterpret_cast<MDRiiGetDirResponse *>(dirInfo.data());
340
341 *data_len = dirInfo.size();
342
343 if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
344 // than MAX_IPMI_BUFFER
345 {
346 phosphor::logging::log<phosphor::logging::level::ERR>(
347 "Data length send from service is invalid");
348 *data_len = 0;
349 return IPMI_CC_RESPONSE_ERROR;
350 }
351
352 std::copy(&dirInfo[0], &dirInfo[*data_len], dataOut);
353
354 return IPMI_CC_OK;
355}
356
357ipmi_ret_t cmd_mdr2_send_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
358 ipmi_request_t request, ipmi_response_t response,
359 ipmi_data_len_t data_len, ipmi_context_t context)
360{
361 auto requestData = reinterpret_cast<const MDRiiSendDirRequest *>(request);
362 std::vector<uint8_t> idVector;
363 bool teminate = false;
364
365 if (*data_len != sizeof(MDRiiSendDirRequest))
366 {
367 *data_len = 0;
368 return IPMI_CC_REQ_DATA_LEN_INVALID;
369 }
370
371 *data_len = 0;
372
373 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
374
375 if (mdrv2 == nullptr)
376 {
377 mdrv2 = std::make_unique<MDRV2>();
378 }
379
380 int agentIndex = mdrv2->agentLookup(requestData->agentId);
381 if (agentIndex == -1)
382 {
383 phosphor::logging::log<phosphor::logging::level::ERR>(
384 "Unknown agent id",
385 phosphor::logging::entry("ID=%x", requestData->agentId));
386 return IPMI_CC_PARM_OUT_OF_RANGE;
387 }
388
389 if ((requestData->dirIndex + requestData->returnedEntries) > maxDirEntries)
390 {
391 phosphor::logging::log<phosphor::logging::level::ERR>(
392 "Too many directory entries");
393 return IPMI_CC_STORGE_LEAK;
394 }
395
396 sdbusplus::message::message method = bus.new_method_call(
397 service.c_str(), mdrv2Path, mdrv2Interface, "SendDirectoryInformation");
398 method.append(requestData->dirVersion, requestData->dirIndex,
399 requestData->returnedEntries, requestData->remainingEntries);
400 uint8_t *reqPoint;
401 for (int index = 0; index < requestData->returnedEntries; index++)
402 {
403 reqPoint = (uint8_t *)&(requestData->data[index]);
404 std::copy(reqPoint, sizeof(Mdr2DirEntry) + reqPoint, idVector.data());
405 }
406 method.append(idVector);
407
408 try
409 {
410 sdbusplus::message::message reply = bus.call(method);
411 reply.read(teminate);
412 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700413 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700414 {
415 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700416 "Error send dir", phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700417 phosphor::logging::entry("SERVICE=%s", service.c_str()),
418 phosphor::logging::entry("PATH=%s", mdrv2Path));
419 return IPMI_CC_RESPONSE_ERROR;
420 }
421
422 *data_len = 1;
423 if (teminate == false)
424 *(static_cast<uint8_t *>(response)) = 0;
425 else
426 *(static_cast<uint8_t *>(response)) = 1;
427 return IPMI_CC_OK;
428}
429
430ipmi_ret_t cmd_mdr2_get_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
431 ipmi_request_t request,
432 ipmi_response_t response,
433 ipmi_data_len_t data_len,
434 ipmi_context_t context)
435{
436 auto requestData =
437 reinterpret_cast<const MDRiiGetDataInfoRequest *>(request);
438 auto dataOut = reinterpret_cast<uint8_t *>(response);
439 std::vector<uint8_t> res;
440
441 if (*data_len < sizeof(MDRiiGetDataInfoRequest))
442 {
443 *data_len = 0;
444 return IPMI_CC_REQ_DATA_LEN_INVALID;
445 }
446
447 *data_len = 0;
448
449 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
450
451 if (mdrv2 == nullptr)
452 {
453 mdrv2 = std::make_unique<MDRV2>();
454 }
455
456 int agentIndex = mdrv2->agentLookup(requestData->agentId);
457 if (agentIndex == -1)
458 {
459 phosphor::logging::log<phosphor::logging::level::ERR>(
460 "Unknown agent id",
461 phosphor::logging::entry("ID=%x", requestData->agentId));
462 return IPMI_CC_PARM_OUT_OF_RANGE;
463 }
464
465 int idIndex =
466 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
467 sizeof(requestData->dataSetInfo.dataInfo), service);
468
469 if ((idIndex < 0) || (idIndex >= maxDirEntries))
470 {
471 phosphor::logging::log<phosphor::logging::level::ERR>(
472 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
473 return IPMI_CC_PARM_OUT_OF_RANGE;
474 }
475
476 sdbusplus::message::message method = bus.new_method_call(
477 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataInformation");
478
479 method.append(idIndex);
480
481 try
482 {
483 sdbusplus::message::message reply = bus.call(method);
484 reply.read(res);
485 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700486 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700487 {
488 phosphor::logging::log<phosphor::logging::level::ERR>(
489 "Error get data info",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700490 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700491 phosphor::logging::entry("SERVICE=%s", service.c_str()),
492 phosphor::logging::entry("PATH=%s", mdrv2Path));
493 return IPMI_CC_RESPONSE_ERROR;
494 }
495
496 if (res.size() != sizeof(MDRiiGetDataInfoResponse))
497 {
498 phosphor::logging::log<phosphor::logging::level::ERR>(
499 "Get data info response length not invalid");
500 return IPMI_CC_UNSPECIFIED_ERROR;
501 }
502 *data_len = static_cast<size_t>(res.size());
503 std::copy(&res[0], &res[*data_len], dataOut);
504
505 return IPMI_CC_OK;
506}
507
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000508/** @brief implements mdr2 data info offer command
509 * @param agentId - Offer a agent ID to get the "Data Set ID"
510 *
511 * @returns IPMI completion code plus response data
512 * - dataInfo
513 */
514ipmi::RspType<std::vector<uint8_t>> mdr2DataInfoOffer(uint16_t agentId)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700515{
Vernon Mauerya3702c12019-05-22 13:20:59 -0700516 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
517
518 if (mdrv2 == nullptr)
519 {
520 mdrv2 = std::make_unique<MDRV2>();
521 }
522
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000523 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700524 if (agentIndex == -1)
525 {
526 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000527 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
528 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700529 }
530
531 sdbusplus::message::message method = bus.new_method_call(
532 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataOffer");
533
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000534 std::vector<uint8_t> dataInfo;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700535 try
536 {
537 sdbusplus::message::message reply = bus.call(method);
538 reply.read(dataInfo);
539 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700540 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700541 {
542 phosphor::logging::log<phosphor::logging::level::ERR>(
543 "Error send data info offer",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700544 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700545 phosphor::logging::entry("SERVICE=%s", service.c_str()),
546 phosphor::logging::entry("PATH=%s", mdrv2Path));
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000547 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700548 }
549
550 if (dataInfo.size() != sizeof(MDRiiOfferDataInfoResponse))
551 {
552 phosphor::logging::log<phosphor::logging::level::ERR>(
553 "Error send data info offer, return length invalid");
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000554 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700555 }
556
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000557 return ipmi::responseSuccess(dataInfo);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700558}
559
560ipmi_ret_t cmd_mdr2_send_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
561 ipmi_request_t request,
562 ipmi_response_t response,
563 ipmi_data_len_t data_len,
564 ipmi_context_t context)
565{
566 auto requestData =
567 reinterpret_cast<const MDRiiSendDataInfoRequest *>(request);
568 bool entryChanged = true;
569
570 if (*data_len != sizeof(MDRiiSendDataInfoRequest))
571 {
572 *data_len = 0;
573 return IPMI_CC_REQ_DATA_LEN_INVALID;
574 }
575
576 *data_len = 0;
577
578 if (requestData->dataLength > smbiosTableStorageSize)
579 {
580 phosphor::logging::log<phosphor::logging::level::ERR>(
581 "Requested data length is out of SMBIOS Table storage size.");
582 return IPMI_CC_PARM_OUT_OF_RANGE;
583 }
584
585 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
586
587 if (mdrv2 == nullptr)
588 {
589 mdrv2 = std::make_unique<MDRV2>();
590 }
591
592 int agentIndex = mdrv2->agentLookup(requestData->agentId);
593 if (agentIndex == -1)
594 {
595 phosphor::logging::log<phosphor::logging::level::ERR>(
596 "Unknown agent id",
597 phosphor::logging::entry("ID=%x", requestData->agentId));
598 return IPMI_CC_PARM_OUT_OF_RANGE;
599 }
600
601 int idIndex =
602 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
603 sizeof(requestData->dataSetInfo.dataInfo), service);
604
605 if ((idIndex < 0) || (idIndex >= maxDirEntries))
606 {
607 phosphor::logging::log<phosphor::logging::level::ERR>(
608 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
609 return IPMI_CC_PARM_OUT_OF_RANGE;
610 }
611
612 sdbusplus::message::message method = bus.new_method_call(
613 service.c_str(), mdrv2Path, mdrv2Interface, "SendDataInformation");
614
615 method.append((uint8_t)idIndex, requestData->validFlag,
616 requestData->dataLength, requestData->dataVersion,
617 requestData->timeStamp);
618
619 try
620 {
621 sdbusplus::message::message reply = bus.call(method);
622 reply.read(entryChanged);
623 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700624 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700625 {
626 phosphor::logging::log<phosphor::logging::level::ERR>(
627 "Error send data info",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700628 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700629 phosphor::logging::entry("SERVICE=%s", service.c_str()),
630 phosphor::logging::entry("PATH=%s", mdrv2Path));
631 return IPMI_CC_RESPONSE_ERROR;
632 }
633
634 *data_len = 1;
635
636 if (entryChanged)
637 {
638 *(static_cast<uint8_t *>(response)) = 1;
639 }
640 else
641 {
642 *(static_cast<uint8_t *>(response)) = 0;
643 }
644
645 return IPMI_CC_OK;
646}
647
648ipmi_ret_t cmd_mdr2_get_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
649 ipmi_request_t request,
650 ipmi_response_t response,
651 ipmi_data_len_t data_len,
652 ipmi_context_t context)
653{
654 auto requestData =
655 reinterpret_cast<const MDRiiGetDataBlockRequest *>(request);
656 auto responseData = reinterpret_cast<MDRiiGetDataBlockResponse *>(response);
657 std::tuple<uint8_t, uint32_t, uint32_t, std::vector<uint8_t>> res;
658 std::vector<uint8_t> resData;
659 uint8_t status = 1;
660
661 if (*data_len != sizeof(MDRiiGetDataBlockRequest))
662 {
663 *data_len = 0;
664 return IPMI_CC_REQ_DATA_LEN_INVALID;
665 }
666
667 *data_len = 0;
668
669 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
670
671 if (mdrv2 == nullptr)
672 {
673 mdrv2 = std::make_unique<MDRV2>();
674 }
675
676 int agentIndex = mdrv2->agentLookup(requestData->agentId);
677 if (agentIndex == -1)
678 {
679 phosphor::logging::log<phosphor::logging::level::ERR>(
680 "Unknown agent id",
681 phosphor::logging::entry("ID=%x", requestData->agentId));
682 return IPMI_CC_PARM_OUT_OF_RANGE;
683 }
684
685 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
686
687 if ((idIndex < 0) || (idIndex >= maxDirEntries))
688 {
689 phosphor::logging::log<phosphor::logging::level::ERR>(
690 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
691 return IPMI_CC_PARM_OUT_OF_RANGE;
692 }
693
694 if (requestData->xferOffset >= mdrv2->smbiosDir.dir[idIndex].common.size)
695 {
696 phosphor::logging::log<phosphor::logging::level::ERR>(
697 "Offset is outside of range.");
698 return IPMI_CC_PARM_OUT_OF_RANGE;
699 }
700
701 size_t outSize =
702 (requestData->xferLength > mdrv2->smbiosDir.dir[idIndex].xferSize)
703 ? mdrv2->smbiosDir.dir[idIndex].xferSize
704 : requestData->xferLength;
705 if (outSize > UINT_MAX - requestData->xferOffset)
706 {
707 phosphor::logging::log<phosphor::logging::level::ERR>(
708 "Out size and offset are out of range");
709 return IPMI_CC_PARM_OUT_OF_RANGE;
710 }
711 if ((requestData->xferOffset + outSize) >
712 mdrv2->smbiosDir.dir[idIndex].common.size)
713 {
714 outSize =
715 mdrv2->smbiosDir.dir[idIndex].common.size - requestData->xferOffset;
716 }
717
718 responseData->xferLength = outSize;
719 if (responseData->xferLength > requestData->xferLength)
720 {
721 phosphor::logging::log<phosphor::logging::level::ERR>(
722 "Get data block unexpected error.");
723 return IPMI_CC_UNSPECIFIED_ERROR;
724 }
725
726 if ((requestData->xferOffset + outSize) >
727 UINT_MAX -
728 reinterpret_cast<size_t>(mdrv2->smbiosDir.dir[idIndex].dataStorage))
729 {
730 phosphor::logging::log<phosphor::logging::level::ERR>(
731 "Input data to calculate checksum is out of range");
732 return IPMI_CC_PARM_OUT_OF_RANGE;
733 }
734
735 uint32_t u32Checksum = mdrv2->calcChecksum32(
736 mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset,
737 outSize);
738 if (u32Checksum == invalidChecksum)
739 {
740 phosphor::logging::log<phosphor::logging::level::ERR>(
741 "Get data block failed - invalid checksum");
742 return IPMI_CC_OEM_INVALID_CHECKSUM;
743 }
744 responseData->checksum = u32Checksum;
745
746 *data_len = sizeof(responseData->xferLength) +
747 sizeof(responseData->checksum) + outSize;
748
749 if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
750 // than MAX_IPMI_BUFFER
751 {
752 phosphor::logging::log<phosphor::logging::level::ERR>(
753 "Data length send from service is invalid");
754 *data_len = 0;
755 return IPMI_CC_RESPONSE_ERROR;
756 }
757
758 std::copy(
759 &mdrv2->smbiosDir.dir[idIndex].dataStorage[requestData->xferOffset],
760 &mdrv2->smbiosDir.dir[idIndex]
761 .dataStorage[requestData->xferOffset + outSize],
762 responseData->data);
763
764 return IPMI_CC_OK;
765}
766
767ipmi_ret_t cmd_mdr2_send_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
768 ipmi_request_t request,
769 ipmi_response_t response,
770 ipmi_data_len_t data_len,
771 ipmi_context_t context)
772{
773 auto requestData =
774 reinterpret_cast<const MDRiiSendDataBlockRequest *>(request);
775
776 if (*data_len != sizeof(MDRiiSendDataBlockRequest))
777 {
778 *data_len = 0;
779 return IPMI_CC_REQ_DATA_LEN_INVALID;
780 }
781
782 *data_len = 0;
783
784 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
785
786 if (mdrv2 == nullptr)
787 {
788 mdrv2 = std::make_unique<MDRV2>();
789 }
790
791 int agentIndex = mdrv2->agentLookup(requestData->agentId);
792 if (agentIndex == -1)
793 {
794 phosphor::logging::log<phosphor::logging::level::ERR>(
795 "Unknown agent id",
796 phosphor::logging::entry("ID=%x", requestData->agentId));
797 return IPMI_CC_PARM_OUT_OF_RANGE;
798 }
799
800 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
801
802 if ((idIndex < 0) || (idIndex >= maxDirEntries))
803 {
804 phosphor::logging::log<phosphor::logging::level::ERR>(
805 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
806 return IPMI_CC_PARM_OUT_OF_RANGE;
807 }
808
809 if (mdrv2->smbiosIsUpdating(idIndex))
810 {
811 if (requestData->xferOffset > UINT_MAX - requestData->xferLength)
812 {
813 phosphor::logging::log<phosphor::logging::level::ERR>(
814 "Offset and length are out of range");
815 return IPMI_CC_PARM_OUT_OF_RANGE;
816 }
817 if (((requestData->xferOffset + requestData->xferLength) >
818 mdrv2->smbiosDir.dir[idIndex].maxDataSize) ||
819 ((requestData->xferOffset + requestData->xferLength) >
820 mdrv2->smbiosDir.dir[idIndex].common.dataSetSize))
821 {
822 phosphor::logging::log<phosphor::logging::level::ERR>(
823 "Send data block Invalid offset/length");
824 return IPMI_CC_REQUEST_DATA_FIELD_LENGTH_LIMIT_EXCEEDED;
825 }
826 if (reinterpret_cast<size_t>(
827 mdrv2->smbiosDir.dir[idIndex].dataStorage) >
828 UINT_MAX - requestData->xferOffset)
829 {
830 phosphor::logging::log<phosphor::logging::level::ERR>(
831 "Offset is out of range");
832 return IPMI_CC_PARM_OUT_OF_RANGE;
833 }
834 uint8_t *destAddr =
835 mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset;
836 uint8_t *sourceAddr = reinterpret_cast<uint8_t *>(mdrv2->area->vPtr);
837 uint32_t calcChecksum =
838 mdrv2->calcChecksum32(sourceAddr, requestData->xferLength);
839 if (calcChecksum != requestData->checksum)
840 {
841 phosphor::logging::log<phosphor::logging::level::ERR>(
842 "Send data block Invalid checksum");
843 return IPMI_CC_OEM_INVALID_CHECKSUM;
844 }
845 else
846 {
847 if (reinterpret_cast<size_t>(sourceAddr) >
848 UINT_MAX - requestData->xferLength)
849 {
850 phosphor::logging::log<phosphor::logging::level::ERR>(
851 "Length is out of range");
852 return IPMI_CC_PARM_OUT_OF_RANGE;
853 }
854 std::copy(sourceAddr, sourceAddr + requestData->xferLength,
855 destAddr);
856 }
857 }
858 else
859 {
860 phosphor::logging::log<phosphor::logging::level::ERR>(
861 "Send data block failed, other data is updating");
862 return IPMI_CC_DESTINATION_UNAVAILABLE;
863 }
864
865 return IPMI_CC_OK;
866}
867
868bool MDRV2::storeDatatoFlash(MDRSMBIOSHeader *mdrHdr, uint8_t *data)
869{
870 std::ofstream smbiosFile(mdrType2File,
871 std::ios_base::binary | std::ios_base::trunc);
872 if (!smbiosFile.good())
873 {
874 phosphor::logging::log<phosphor::logging::level::ERR>(
875 "Write data from flash error - Open MDRV2 table file failure");
876 return false;
877 }
878
879 try
880 {
881 smbiosFile.write(reinterpret_cast<char *>(mdrHdr),
882 sizeof(MDRSMBIOSHeader));
883 smbiosFile.write(reinterpret_cast<char *>(data), mdrHdr->dataSize);
884 }
885 catch (std::ofstream::failure &e)
886 {
887 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700888 "Write data from flash error - write data error",
889 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -0700890 return false;
891 }
892
893 return true;
894}
895
896void SharedMemoryArea::Initialize(uint32_t addr, uint32_t areaSize)
897{
898 int memDriver = 0;
899
900 // open mem driver for the system memory access
901 memDriver = open("/dev/vgasharedmem", O_RDONLY);
902 if (memDriver < 0)
903 {
904 phosphor::logging::log<phosphor::logging::level::ERR>(
905 "Cannot access mem driver");
906 throw std::system_error(EIO, std::generic_category());
907 }
908
909 // map the system memory
910 vPtr = mmap(NULL, // where to map to: don't mind
911 areaSize, // how many bytes ?
912 PROT_READ, // want to read and write
913 MAP_SHARED, // no copy on write
914 memDriver, // handle to /dev/mem
915 (physicalAddr & pageMask)); // hopefully the Text-buffer :-)
916
917 close(memDriver);
918 if (vPtr == MAP_FAILED)
919 {
920 phosphor::logging::log<phosphor::logging::level::ERR>(
921 "Failed to map share memory");
922 throw std::system_error(EIO, std::generic_category());
923 }
924 size = areaSize;
925 physicalAddr = addr;
926}
927
928bool MDRV2::smbiosUnlock(uint8_t index)
929{
930 bool ret;
931 switch (smbiosDir.dir[index].stage)
932 {
933 case MDR2SMBIOSStatusEnum::mdr2Updating:
934 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updated;
935 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
936
937 timer->stop();
938 smbiosDir.dir[index].lockHandle = 0;
939 ret = true;
940 break;
941
942 case MDR2SMBIOSStatusEnum::mdr2Updated:
943 case MDR2SMBIOSStatusEnum::mdr2Loaded:
944 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
945
946 timer->stop();
947
948 smbiosDir.dir[index].lockHandle = 0;
949 ret = true;
950 break;
951
952 default:
953 break;
954 }
955
956 return ret;
957}
958
959bool MDRV2::smbiosTryLock(uint8_t flag, uint8_t index, uint16_t *session,
960 uint16_t timeout)
961{
962 bool ret = false;
963 uint32_t u32Status = 0;
964
965 if (timeout == 0)
966 {
967 timeout = defaultTimeout;
968 }
969 std::chrono::microseconds usec(timeout * sysClock);
970
971 switch (smbiosDir.dir[index].stage)
972 {
973 case MDR2SMBIOSStatusEnum::mdr2Updating:
974 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
975 {
976 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
977 timer->start(usec);
978 lockIndex = index;
979
980 *session = getSessionHandle(&smbiosDir);
981 smbiosDir.dir[index].lockHandle = *session;
982 ret = true;
983 }
984 break;
985 case MDR2SMBIOSStatusEnum::mdr2Init:
986 if (flag)
987 {
988 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updating;
989 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
990 timer->start(usec);
991 lockIndex = index;
992
993 *session = getSessionHandle(&smbiosDir);
994 smbiosDir.dir[index].lockHandle = *session;
995 ret = true;
996 }
997 break;
998
999 case MDR2SMBIOSStatusEnum::mdr2Updated:
1000 case MDR2SMBIOSStatusEnum::mdr2Loaded:
1001 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
1002 {
1003 if (flag)
1004 {
1005 smbiosDir.dir[index].stage =
1006 MDR2SMBIOSStatusEnum::mdr2Updating;
1007 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
1008 }
1009 else
1010 {
1011 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
1012 }
1013
1014 timer->start(usec);
1015 lockIndex = index;
1016
1017 *session = getSessionHandle(&smbiosDir);
1018 smbiosDir.dir[index].lockHandle = *session;
1019 ret = true;
1020 }
1021 break;
1022
1023 default:
1024 break;
1025 }
1026 return ret;
1027}
1028
1029void MDRV2::timeoutHandler()
1030{
1031 smbiosUnlock(lockIndex);
1032 mdrv2->area.reset(nullptr);
1033}
1034
1035ipmi_ret_t cmd_mdr2_lock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1036 ipmi_request_t request, ipmi_response_t response,
1037 ipmi_data_len_t data_len, ipmi_context_t context)
1038{
1039 auto requestData = reinterpret_cast<const MDRiiLockDataRequest *>(request);
1040 auto responseData = reinterpret_cast<MDRiiLockDataResponse *>(response);
1041 uint16_t session = 0;
1042
1043 std::tuple<bool, uint8_t, uint16_t, uint32_t, uint32_t, uint32_t> res;
1044
1045 if (*data_len < sizeof(MDRiiLockDataRequest))
1046 {
1047 *data_len = 0;
1048 return IPMI_CC_REQ_DATA_LEN_INVALID;
1049 }
1050
1051 *data_len = 0;
1052
1053 if (mdrv2 == nullptr)
1054 {
1055 mdrv2 = std::make_unique<MDRV2>();
1056 }
1057
1058 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1059 if (agentIndex == -1)
1060 {
1061 phosphor::logging::log<phosphor::logging::level::ERR>(
1062 "Unknown agent id",
1063 phosphor::logging::entry("ID=%x", requestData->agentId));
1064 return IPMI_CC_PARM_OUT_OF_RANGE;
1065 }
1066
1067 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1068
1069 int idIndex =
1070 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
1071 sizeof(requestData->dataSetInfo.dataInfo), service);
1072
1073 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1074 {
1075 phosphor::logging::log<phosphor::logging::level::ERR>(
1076 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1077 return IPMI_CC_PARM_OUT_OF_RANGE;
1078 }
1079
1080 if (!mdrv2->smbiosTryLock(0, idIndex, &session, requestData->timeout))
1081 {
1082 phosphor::logging::log<phosphor::logging::level::ERR>(
1083 "Lock Data failed - cannot lock idIndex");
1084 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
1085 }
1086
1087 *data_len = sizeof(MDRiiLockDataResponse);
1088
1089 responseData->mdrVersion = mdr2Version;
1090 responseData->lockHandle = session;
1091 responseData->dataLength = mdrv2->smbiosDir.dir[idIndex].common.size;
1092 responseData->xferAddress = mdrv2->smbiosDir.dir[idIndex].xferBuff;
1093 responseData->xferLength = mdrv2->smbiosDir.dir[idIndex].xferSize;
1094
1095 return IPMI_CC_OK;
1096}
1097
1098ipmi_ret_t cmd_mdr2_unlock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1099 ipmi_request_t request,
1100 ipmi_response_t response,
1101 ipmi_data_len_t data_len,
1102 ipmi_context_t context)
1103{
1104 phosphor::logging::log<phosphor::logging::level::ERR>("unlock data");
1105 auto requestData =
1106 reinterpret_cast<const MDRiiUnlockDataRequest *>(request);
1107
1108 if (*data_len != sizeof(MDRiiUnlockDataRequest))
1109 {
1110 *data_len = 0;
1111 return IPMI_CC_REQ_DATA_LEN_INVALID;
1112 }
1113
1114 *data_len = 0;
1115
1116 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1117
1118 if (mdrv2 == nullptr)
1119 {
1120 mdrv2 = std::make_unique<MDRV2>();
1121 }
1122
1123 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1124 if (agentIndex == -1)
1125 {
1126 phosphor::logging::log<phosphor::logging::level::ERR>(
1127 "Unknown agent id",
1128 phosphor::logging::entry("ID=%x", requestData->agentId));
1129 return IPMI_CC_PARM_OUT_OF_RANGE;
1130 }
1131
1132 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
1133
1134 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1135 {
1136 phosphor::logging::log<phosphor::logging::level::ERR>(
1137 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1138 return IPMI_CC_PARM_OUT_OF_RANGE;
1139 }
1140
1141 if (!mdrv2->smbiosUnlock(idIndex))
1142 {
1143 phosphor::logging::log<phosphor::logging::level::ERR>(
1144 "Unlock Data failed - cannot unlock idIndex");
1145 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
1146 }
1147
1148 return IPMI_CC_OK;
1149}
1150
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001151/**
1152@brief This command is executed after POST BIOS to get the session info.
1153
1154@param - agentId, dataInfo, dataLength, xferAddress, xferLength, timeout.
1155
1156@return xferStartAck and session on success.
1157**/
1158ipmi::RspType<uint8_t, uint16_t>
1159 cmd_mdr2_data_start(uint16_t agentId, std::array<uint8_t, 16> dataInfo,
1160 uint32_t dataLength, uint32_t xferAddress,
1161 uint32_t xferLength, uint16_t timeout)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001162{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001163 uint16_t session = 0;
1164
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001165 if (dataLength > smbiosTableStorageSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001166 {
1167 phosphor::logging::log<phosphor::logging::level::ERR>(
1168 "Requested data length is out of SMBIOS Table storage size.");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001169 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001170 }
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001171 if ((xferLength + xferAddress) > mdriiSMSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001172 {
1173 phosphor::logging::log<phosphor::logging::level::ERR>(
1174 "Invalid data address and size");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001175 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001176 }
1177
1178 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1179
1180 if (mdrv2 == nullptr)
1181 {
1182 mdrv2 = std::make_unique<MDRV2>();
1183 }
1184
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001185 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001186 if (agentIndex == -1)
1187 {
1188 phosphor::logging::log<phosphor::logging::level::ERR>(
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001189 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1190 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001191 }
1192
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001193 int idIndex = mdrv2->findDataId(dataInfo.data(), sizeof(dataInfo), service);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001194
1195 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1196 {
1197 phosphor::logging::log<phosphor::logging::level::ERR>(
1198 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001199 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001200 }
1201
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001202 if (mdrv2->smbiosTryLock(1, idIndex, &session, timeout))
Vernon Mauerya3702c12019-05-22 13:20:59 -07001203 {
1204 try
1205 {
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001206 mdrv2->area =
1207 std::make_unique<SharedMemoryArea>(xferAddress, xferLength);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001208 }
1209 catch (const std::system_error &e)
1210 {
1211 mdrv2->smbiosUnlock(idIndex);
1212 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001213 "Unable to access share memory",
1214 phosphor::logging::entry("ERROR=%s", e.what()));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001215 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001216 }
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001217 mdrv2->smbiosDir.dir[idIndex].common.size = dataLength;
Vernon Mauerya3702c12019-05-22 13:20:59 -07001218 mdrv2->smbiosDir.dir[idIndex].lockHandle = session;
1219 if (-1 ==
1220 mdrv2->syncDirCommonData(
1221 idIndex, mdrv2->smbiosDir.dir[idIndex].common.size, service))
1222 {
1223 phosphor::logging::log<phosphor::logging::level::ERR>(
1224 "Unable to sync data to service");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001225 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001226 }
1227 }
1228 else
1229 {
1230 phosphor::logging::log<phosphor::logging::level::ERR>(
1231 "Canot lock smbios");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001232 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001233 }
1234
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001235 static constexpr uint8_t xferStartAck = 1;
Vernon Mauerya3702c12019-05-22 13:20:59 -07001236
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001237 return ipmi::responseSuccess(xferStartAck, session);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001238}
1239
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001240/**
1241@brief This command is executed to close the session.
1242
1243@param - agentId, lockHandle.
1244
1245@return completion code on success.
1246**/
1247ipmi::RspType<> cmd_mdr2_data_done(uint16_t agentId, uint16_t lockHandle)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001248{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001249
1250 if (mdrv2 == nullptr)
1251 {
1252 mdrv2 = std::make_unique<MDRV2>();
1253 }
1254
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001255 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001256 if (agentIndex == -1)
1257 {
1258 phosphor::logging::log<phosphor::logging::level::ERR>(
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001259 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1260 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001261 }
1262
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001263 int idIndex = mdrv2->findLockHandle(lockHandle);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001264
1265 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1266 {
1267 phosphor::logging::log<phosphor::logging::level::ERR>(
1268 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001269 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001270 }
1271
1272 if (!mdrv2->smbiosUnlock(idIndex))
1273 {
1274 phosphor::logging::log<phosphor::logging::level::ERR>(
1275 "Send data done failed - cannot unlock idIndex");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001276 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001277 }
1278
1279 mdrv2->area.reset(nullptr);
1280 MDRSMBIOSHeader mdr2Smbios;
1281 mdr2Smbios.mdrType = mdrTypeII;
1282 mdr2Smbios.dirVer = mdrv2->smbiosDir.dir[0].common.dataVersion;
1283 mdr2Smbios.timestamp = mdrv2->smbiosDir.dir[0].common.timestamp;
1284 mdr2Smbios.dataSize = mdrv2->smbiosDir.dir[0].common.size;
1285
1286 if (access(smbiosPath, 0) == -1)
1287 {
1288 int flag = mkdir(smbiosPath, S_IRWXU);
1289 if (flag != 0)
1290 {
1291 phosphor::logging::log<phosphor::logging::level::ERR>(
1292 "create folder failed for writting smbios file");
1293 }
1294 }
1295 if (!mdrv2->storeDatatoFlash(
1296 &mdr2Smbios, mdrv2->smbiosDir.dir[smbiosDirIndex].dataStorage))
1297 {
1298 phosphor::logging::log<phosphor::logging::level::ERR>(
1299 "MDR2 Store data to flash failed");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001300 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001301 }
Vernon Mauerya3702c12019-05-22 13:20:59 -07001302 bool status = false;
1303 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1304 sdbusplus::message::message method = bus.new_method_call(
1305 service.c_str(), mdrv2Path, mdrv2Interface, "AgentSynchronizeData");
1306
1307 try
1308 {
1309 sdbusplus::message::message reply = bus.call(method);
1310 reply.read(status);
1311 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001312 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001313 {
1314 phosphor::logging::log<phosphor::logging::level::ERR>(
1315 "Error Sync data with service",
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001316 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -07001317 phosphor::logging::entry("SERVICE=%s", service.c_str()),
1318 phosphor::logging::entry("PATH=%s", mdrv2Path));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001319 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001320 }
1321
1322 if (!status)
1323 {
1324 phosphor::logging::log<phosphor::logging::level::ERR>(
1325 "Sync data with service failure");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001326 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001327 }
1328
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001329 return ipmi::responseSuccess();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001330}
1331
1332static void register_netfn_smbiosmdrv2_functions(void)
1333{
1334 // MDR V2 Command
1335 // <Get MDRII Status Command>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001336 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1337 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_AGENT_STATUS,
1338 ipmi::Privilege::Operator, mdr2AgentStatus);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001339
1340 // <Get MDRII Directory Command>
1341 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1342 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DIR, NULL,
1343 cmd_mdr2_get_dir, PRIVILEGE_OPERATOR);
1344
1345 // <Send MDRII Directory Command>
1346 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1347 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DIR, NULL,
1348 cmd_mdr2_send_dir, PRIVILEGE_OPERATOR);
1349
1350 // <Get MDRII Data Info Command>
1351 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1352 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_INFO,
1353 NULL, cmd_mdr2_get_data_info, PRIVILEGE_OPERATOR);
1354
1355 // <Send MDRII Info Offer>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001356 ipmi::registerHandler(
1357 ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1358 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO_OFFER,
1359 ipmi::Privilege::Operator, mdr2DataInfoOffer);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001360
1361 // <Send MDRII Data Info>
1362 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1363 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO,
1364 NULL, cmd_mdr2_send_data_info, PRIVILEGE_OPERATOR);
1365
1366 // <Get MDRII Data Block Command>
1367 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1368 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_BLOCK,
1369 NULL, cmd_mdr2_get_data_block, PRIVILEGE_OPERATOR);
1370
1371 // <Send MDRII Data Block>
1372 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1373 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_BLOCK,
1374 NULL, cmd_mdr2_send_data_block, PRIVILEGE_OPERATOR);
1375
1376 // <Lock MDRII Data Command>
1377 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1378 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_LOCK_DATA, NULL,
1379 cmd_mdr2_lock_data, PRIVILEGE_OPERATOR);
1380
1381 // <Unlock MDRII Data Command>
1382 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1383 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_UNLOCK_DATA,
1384 NULL, cmd_mdr2_unlock_data, PRIVILEGE_OPERATOR);
1385
1386 // <Send MDRII Data Start>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001387 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1388 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_START,
1389 ipmi::Privilege::Operator, cmd_mdr2_data_start);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001390
1391 // <Send MDRII Data Done>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001392 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1393 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_DONE,
1394 ipmi::Privilege::Operator, cmd_mdr2_data_done);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001395}