blob: a6807ab68ac8196457b4d70b8f976dde2e6537f8 [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
39namespace variant_ns = sdbusplus::message::variant_ns;
40
41static void register_netfn_smbiosmdrv2_functions() __attribute__((constructor));
42static sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
43
44int MDRV2::agentLookup(const uint16_t &agentId)
45{
46 int agentIndex = -1;
47
48 if (lastAgentId == agentId)
49 {
50 return lastAgentIndex;
51 }
52
53 if (agentId == smbiosAgentId)
54 {
55 return firstAgentIndex;
56 }
57
58 return agentIndex;
59}
60
61int MDRV2::sdplusMdrv2GetProperty(const std::string &name,
62 sdbusplus::message::variant<uint8_t> &value,
63 const std::string &service)
64{
65 sdbusplus::message::message method =
66 bus.new_method_call(service.c_str(), mdrv2Path, dbusProperties, "Get");
67 method.append(mdrv2Interface, name);
68
69 sdbusplus::message::message reply = bus.call(method);
70
71 try
72 {
73 sdbusplus::message::message reply = bus.call(method);
74 reply.read(value);
75 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -070076 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -070077 {
78 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -070079 "Error get property, sdbusplus call failed",
80 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -070081 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 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700101 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700102 {
103 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700104 "Error sync dir common data with service",
105 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -0700106 return -1;
107 }
108
109 if (commonData.size() < syncDirCommonSize)
110 {
111 phosphor::logging::log<phosphor::logging::level::ERR>(
112 "Error sync dir common data - data length invalid");
113 return -1;
114 }
115 smbiosDir.dir[idIndex].common.dataSetSize = commonData.at(0);
116 smbiosDir.dir[idIndex].common.dataVersion = commonData.at(1);
117 smbiosDir.dir[idIndex].common.timestamp = commonData.at(2);
118
119 return 0;
120}
121
122int MDRV2::findDataId(const uint8_t *dataInfo, const size_t &len,
123 const std::string &service)
124{
125 int idIndex = -1;
126
127 if (dataInfo == nullptr)
128 {
129 phosphor::logging::log<phosphor::logging::level::ERR>(
130 "Error dataInfo, input is null point");
131 return -1;
132 }
133
134 sdbusplus::message::message method = bus.new_method_call(
135 service.c_str(), mdrv2Path, mdrv2Interface, "FindIdIndex");
136 std::vector<uint8_t> info;
137 info.resize(len);
138 std::copy(dataInfo, dataInfo + len, info.data());
139 method.append(info);
140
141 try
142 {
143 sdbusplus::message::message reply = bus.call(method);
144 reply.read(idIndex);
145 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700146 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700147 {
148 phosphor::logging::log<phosphor::logging::level::ERR>(
149 "Error find id index",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700150 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700151 phosphor::logging::entry("SERVICE=%s", service.c_str()),
152 phosphor::logging::entry("PATH=%s", mdrv2Path));
153 return -1;
154 }
155
156 return idIndex;
157}
158
159uint16_t MDRV2::getSessionHandle(Mdr2DirStruct *dir)
160{
161 if (dir == NULL)
162 {
163 phosphor::logging::log<phosphor::logging::level::ERR>(
164 "Empty dir point");
165 return 0;
166 }
167 dir->sessionHandle++;
168 if (dir->sessionHandle == 0)
169 {
170 dir->sessionHandle = 1;
171 }
172
173 return dir->sessionHandle;
174}
175
176int MDRV2::findLockHandle(const uint16_t &lockHandle)
177{
178 int idIndex = -1;
179
180 for (int index = 0; index < smbiosDir.dirEntries; index++)
181 {
182 if (lockHandle == smbiosDir.dir[index].lockHandle)
183 {
184 return index;
185 }
186 }
187
188 return idIndex;
189}
190
191bool MDRV2::smbiosIsUpdating(uint8_t index)
192{
193 if (index > maxDirEntries)
194 {
195 return false;
196 }
197 if (smbiosDir.dir[index].stage == MDR2SMBIOSStatusEnum::mdr2Updating)
198 {
199 return true;
200 }
201
202 return false;
203}
204
205uint32_t MDRV2::calcChecksum32(uint8_t *buf, uint32_t len)
206{
207 uint32_t sum = 0;
208
209 if (buf == nullptr)
210 {
211 return invalidChecksum;
212 }
213
214 for (uint32_t index = 0; index < len; index++)
215 {
216 sum += buf[index];
217 }
218
219 return sum;
220}
221
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000222/** @brief implements mdr2 agent status command
223 * @param agentId
224 * @param dirVersion
225 *
226 * @returns IPMI completion code plus response data
227 * - mdrVersion
228 * - agentVersion
229 * - dirVersion
230 * - dirEntries
231 * - dataRequest
232 */
233ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t, uint8_t>
234 mdr2AgentStatus(uint16_t agentId, uint8_t dirVersion)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700235{
Vernon Mauerya3702c12019-05-22 13:20:59 -0700236 if (mdrv2 == nullptr)
237 {
238 mdrv2 = std::make_unique<MDRV2>();
239 }
240
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000241 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700242 if (agentIndex == -1)
243 {
244 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000245 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
246 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700247 }
248
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000249 constexpr uint8_t mdrVersion = mdr2Version;
250 constexpr uint8_t agentVersion = smbiosAgentVersion;
251 uint8_t dirVersionResp = mdrv2->smbiosDir.dirVersion;
252 uint8_t dirEntries = mdrv2->smbiosDir.dirEntries;
253 uint8_t dataRequest;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700254
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000255 if (mdrv2->smbiosDir.remoteDirVersion != dirVersion)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700256 {
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000257 mdrv2->smbiosDir.remoteDirVersion = dirVersion;
258 dataRequest =
Vernon Mauerya3702c12019-05-22 13:20:59 -0700259 static_cast<uint8_t>(DirDataRequestEnum::dirDataRequested);
260 }
261 else
262 {
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000263 dataRequest =
Vernon Mauerya3702c12019-05-22 13:20:59 -0700264 static_cast<uint8_t>(DirDataRequestEnum::dirDataNotRequested);
265 }
266
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000267 return ipmi::responseSuccess(mdrVersion, agentVersion, dirVersionResp,
268 dirEntries, dataRequest);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700269}
270
271ipmi_ret_t cmd_mdr2_get_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
272 ipmi_request_t request, ipmi_response_t response,
273 ipmi_data_len_t data_len, ipmi_context_t context)
274{
275 auto requestData = reinterpret_cast<const MDRiiGetDirRequest *>(request);
276 auto dataOut = reinterpret_cast<uint8_t *>(response);
277 std::vector<uint8_t> dirInfo;
278
279 if (*data_len != sizeof(MDRiiGetDirRequest))
280 {
281 *data_len = 0;
282 return IPMI_CC_REQ_DATA_LEN_INVALID;
283 }
284
285 *data_len = 0;
286
287 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
288
289 if (mdrv2 == nullptr)
290 {
291 mdrv2 = std::make_unique<MDRV2>();
292 }
293
294 int agentIndex = mdrv2->agentLookup(requestData->agentId);
295 if (agentIndex == -1)
296 {
297 phosphor::logging::log<phosphor::logging::level::ERR>(
298 "Unknown agent id",
299 phosphor::logging::entry("ID=%x", requestData->agentId));
300 return IPMI_CC_PARM_OUT_OF_RANGE;
301 }
302
303 sdbusplus::message::variant<uint8_t> value = 0;
304 if (0 != mdrv2->sdplusMdrv2GetProperty("DirectoryEntries", value, service))
305 {
306 phosphor::logging::log<phosphor::logging::level::ERR>(
307 "Error getting DirEnries");
308 return IPMI_CC_UNSPECIFIED_ERROR;
309 }
310 if (requestData->dirIndex > variant_ns::get<uint8_t>(value))
311 {
312 return IPMI_CC_PARM_OUT_OF_RANGE;
313 }
314
315 sdbusplus::message::message method = bus.new_method_call(
316 service.c_str(), mdrv2Path, mdrv2Interface, "GetDirectoryInformation");
317
318 method.append(requestData->dirIndex);
319
320 try
321 {
322 sdbusplus::message::message reply = bus.call(method);
323 reply.read(dirInfo);
324 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700325 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700326 {
327 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700328 "Error get dir", phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700329 phosphor::logging::entry("SERVICE=%s", service.c_str()),
330 phosphor::logging::entry("PATH=%s", mdrv2Path));
331 return IPMI_CC_RESPONSE_ERROR;
332 }
333
334 if (dirInfo.size() < sizeof(MDRiiGetDirResponse))
335 {
336 phosphor::logging::log<phosphor::logging::level::ERR>(
337 "Error get dir, response length invalid");
338 return IPMI_CC_UNSPECIFIED_ERROR;
339 }
340
341 auto responseData = reinterpret_cast<MDRiiGetDirResponse *>(dirInfo.data());
342
343 *data_len = dirInfo.size();
344
345 if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
346 // than MAX_IPMI_BUFFER
347 {
348 phosphor::logging::log<phosphor::logging::level::ERR>(
349 "Data length send from service is invalid");
350 *data_len = 0;
351 return IPMI_CC_RESPONSE_ERROR;
352 }
353
354 std::copy(&dirInfo[0], &dirInfo[*data_len], dataOut);
355
356 return IPMI_CC_OK;
357}
358
359ipmi_ret_t cmd_mdr2_send_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
360 ipmi_request_t request, ipmi_response_t response,
361 ipmi_data_len_t data_len, ipmi_context_t context)
362{
363 auto requestData = reinterpret_cast<const MDRiiSendDirRequest *>(request);
364 std::vector<uint8_t> idVector;
365 bool teminate = false;
366
367 if (*data_len != sizeof(MDRiiSendDirRequest))
368 {
369 *data_len = 0;
370 return IPMI_CC_REQ_DATA_LEN_INVALID;
371 }
372
373 *data_len = 0;
374
375 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
376
377 if (mdrv2 == nullptr)
378 {
379 mdrv2 = std::make_unique<MDRV2>();
380 }
381
382 int agentIndex = mdrv2->agentLookup(requestData->agentId);
383 if (agentIndex == -1)
384 {
385 phosphor::logging::log<phosphor::logging::level::ERR>(
386 "Unknown agent id",
387 phosphor::logging::entry("ID=%x", requestData->agentId));
388 return IPMI_CC_PARM_OUT_OF_RANGE;
389 }
390
391 if ((requestData->dirIndex + requestData->returnedEntries) > maxDirEntries)
392 {
393 phosphor::logging::log<phosphor::logging::level::ERR>(
394 "Too many directory entries");
395 return IPMI_CC_STORGE_LEAK;
396 }
397
398 sdbusplus::message::message method = bus.new_method_call(
399 service.c_str(), mdrv2Path, mdrv2Interface, "SendDirectoryInformation");
400 method.append(requestData->dirVersion, requestData->dirIndex,
401 requestData->returnedEntries, requestData->remainingEntries);
402 uint8_t *reqPoint;
403 for (int index = 0; index < requestData->returnedEntries; index++)
404 {
405 reqPoint = (uint8_t *)&(requestData->data[index]);
406 std::copy(reqPoint, sizeof(Mdr2DirEntry) + reqPoint, idVector.data());
407 }
408 method.append(idVector);
409
410 try
411 {
412 sdbusplus::message::message reply = bus.call(method);
413 reply.read(teminate);
414 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700415 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700416 {
417 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700418 "Error send dir", phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700419 phosphor::logging::entry("SERVICE=%s", service.c_str()),
420 phosphor::logging::entry("PATH=%s", mdrv2Path));
421 return IPMI_CC_RESPONSE_ERROR;
422 }
423
424 *data_len = 1;
425 if (teminate == false)
426 *(static_cast<uint8_t *>(response)) = 0;
427 else
428 *(static_cast<uint8_t *>(response)) = 1;
429 return IPMI_CC_OK;
430}
431
432ipmi_ret_t cmd_mdr2_get_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
433 ipmi_request_t request,
434 ipmi_response_t response,
435 ipmi_data_len_t data_len,
436 ipmi_context_t context)
437{
438 auto requestData =
439 reinterpret_cast<const MDRiiGetDataInfoRequest *>(request);
440 auto dataOut = reinterpret_cast<uint8_t *>(response);
441 std::vector<uint8_t> res;
442
443 if (*data_len < sizeof(MDRiiGetDataInfoRequest))
444 {
445 *data_len = 0;
446 return IPMI_CC_REQ_DATA_LEN_INVALID;
447 }
448
449 *data_len = 0;
450
451 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
452
453 if (mdrv2 == nullptr)
454 {
455 mdrv2 = std::make_unique<MDRV2>();
456 }
457
458 int agentIndex = mdrv2->agentLookup(requestData->agentId);
459 if (agentIndex == -1)
460 {
461 phosphor::logging::log<phosphor::logging::level::ERR>(
462 "Unknown agent id",
463 phosphor::logging::entry("ID=%x", requestData->agentId));
464 return IPMI_CC_PARM_OUT_OF_RANGE;
465 }
466
467 int idIndex =
468 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
469 sizeof(requestData->dataSetInfo.dataInfo), service);
470
471 if ((idIndex < 0) || (idIndex >= maxDirEntries))
472 {
473 phosphor::logging::log<phosphor::logging::level::ERR>(
474 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
475 return IPMI_CC_PARM_OUT_OF_RANGE;
476 }
477
478 sdbusplus::message::message method = bus.new_method_call(
479 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataInformation");
480
481 method.append(idIndex);
482
483 try
484 {
485 sdbusplus::message::message reply = bus.call(method);
486 reply.read(res);
487 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700488 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700489 {
490 phosphor::logging::log<phosphor::logging::level::ERR>(
491 "Error get data info",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700492 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700493 phosphor::logging::entry("SERVICE=%s", service.c_str()),
494 phosphor::logging::entry("PATH=%s", mdrv2Path));
495 return IPMI_CC_RESPONSE_ERROR;
496 }
497
498 if (res.size() != sizeof(MDRiiGetDataInfoResponse))
499 {
500 phosphor::logging::log<phosphor::logging::level::ERR>(
501 "Get data info response length not invalid");
502 return IPMI_CC_UNSPECIFIED_ERROR;
503 }
504 *data_len = static_cast<size_t>(res.size());
505 std::copy(&res[0], &res[*data_len], dataOut);
506
507 return IPMI_CC_OK;
508}
509
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000510/** @brief implements mdr2 data info offer command
511 * @param agentId - Offer a agent ID to get the "Data Set ID"
512 *
513 * @returns IPMI completion code plus response data
514 * - dataInfo
515 */
516ipmi::RspType<std::vector<uint8_t>> mdr2DataInfoOffer(uint16_t agentId)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700517{
Vernon Mauerya3702c12019-05-22 13:20:59 -0700518 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
519
520 if (mdrv2 == nullptr)
521 {
522 mdrv2 = std::make_unique<MDRV2>();
523 }
524
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000525 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700526 if (agentIndex == -1)
527 {
528 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000529 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
530 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700531 }
532
533 sdbusplus::message::message method = bus.new_method_call(
534 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataOffer");
535
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000536 std::vector<uint8_t> dataInfo;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700537 try
538 {
539 sdbusplus::message::message reply = bus.call(method);
540 reply.read(dataInfo);
541 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700542 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700543 {
544 phosphor::logging::log<phosphor::logging::level::ERR>(
545 "Error send data info offer",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700546 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700547 phosphor::logging::entry("SERVICE=%s", service.c_str()),
548 phosphor::logging::entry("PATH=%s", mdrv2Path));
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000549 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700550 }
551
552 if (dataInfo.size() != sizeof(MDRiiOfferDataInfoResponse))
553 {
554 phosphor::logging::log<phosphor::logging::level::ERR>(
555 "Error send data info offer, return length invalid");
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000556 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700557 }
558
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000559 return ipmi::responseSuccess(dataInfo);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700560}
561
562ipmi_ret_t cmd_mdr2_send_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
563 ipmi_request_t request,
564 ipmi_response_t response,
565 ipmi_data_len_t data_len,
566 ipmi_context_t context)
567{
568 auto requestData =
569 reinterpret_cast<const MDRiiSendDataInfoRequest *>(request);
570 bool entryChanged = true;
571
572 if (*data_len != sizeof(MDRiiSendDataInfoRequest))
573 {
574 *data_len = 0;
575 return IPMI_CC_REQ_DATA_LEN_INVALID;
576 }
577
578 *data_len = 0;
579
580 if (requestData->dataLength > smbiosTableStorageSize)
581 {
582 phosphor::logging::log<phosphor::logging::level::ERR>(
583 "Requested data length is out of SMBIOS Table storage size.");
584 return IPMI_CC_PARM_OUT_OF_RANGE;
585 }
586
587 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
588
589 if (mdrv2 == nullptr)
590 {
591 mdrv2 = std::make_unique<MDRV2>();
592 }
593
594 int agentIndex = mdrv2->agentLookup(requestData->agentId);
595 if (agentIndex == -1)
596 {
597 phosphor::logging::log<phosphor::logging::level::ERR>(
598 "Unknown agent id",
599 phosphor::logging::entry("ID=%x", requestData->agentId));
600 return IPMI_CC_PARM_OUT_OF_RANGE;
601 }
602
603 int idIndex =
604 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
605 sizeof(requestData->dataSetInfo.dataInfo), service);
606
607 if ((idIndex < 0) || (idIndex >= maxDirEntries))
608 {
609 phosphor::logging::log<phosphor::logging::level::ERR>(
610 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
611 return IPMI_CC_PARM_OUT_OF_RANGE;
612 }
613
614 sdbusplus::message::message method = bus.new_method_call(
615 service.c_str(), mdrv2Path, mdrv2Interface, "SendDataInformation");
616
617 method.append((uint8_t)idIndex, requestData->validFlag,
618 requestData->dataLength, requestData->dataVersion,
619 requestData->timeStamp);
620
621 try
622 {
623 sdbusplus::message::message reply = bus.call(method);
624 reply.read(entryChanged);
625 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700626 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700627 {
628 phosphor::logging::log<phosphor::logging::level::ERR>(
629 "Error send data info",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700630 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700631 phosphor::logging::entry("SERVICE=%s", service.c_str()),
632 phosphor::logging::entry("PATH=%s", mdrv2Path));
633 return IPMI_CC_RESPONSE_ERROR;
634 }
635
636 *data_len = 1;
637
638 if (entryChanged)
639 {
640 *(static_cast<uint8_t *>(response)) = 1;
641 }
642 else
643 {
644 *(static_cast<uint8_t *>(response)) = 0;
645 }
646
647 return IPMI_CC_OK;
648}
649
650ipmi_ret_t cmd_mdr2_get_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
651 ipmi_request_t request,
652 ipmi_response_t response,
653 ipmi_data_len_t data_len,
654 ipmi_context_t context)
655{
656 auto requestData =
657 reinterpret_cast<const MDRiiGetDataBlockRequest *>(request);
658 auto responseData = reinterpret_cast<MDRiiGetDataBlockResponse *>(response);
659 std::tuple<uint8_t, uint32_t, uint32_t, std::vector<uint8_t>> res;
660 std::vector<uint8_t> resData;
661 uint8_t status = 1;
662
663 if (*data_len != sizeof(MDRiiGetDataBlockRequest))
664 {
665 *data_len = 0;
666 return IPMI_CC_REQ_DATA_LEN_INVALID;
667 }
668
669 *data_len = 0;
670
671 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
672
673 if (mdrv2 == nullptr)
674 {
675 mdrv2 = std::make_unique<MDRV2>();
676 }
677
678 int agentIndex = mdrv2->agentLookup(requestData->agentId);
679 if (agentIndex == -1)
680 {
681 phosphor::logging::log<phosphor::logging::level::ERR>(
682 "Unknown agent id",
683 phosphor::logging::entry("ID=%x", requestData->agentId));
684 return IPMI_CC_PARM_OUT_OF_RANGE;
685 }
686
687 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
688
689 if ((idIndex < 0) || (idIndex >= maxDirEntries))
690 {
691 phosphor::logging::log<phosphor::logging::level::ERR>(
692 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
693 return IPMI_CC_PARM_OUT_OF_RANGE;
694 }
695
696 if (requestData->xferOffset >= mdrv2->smbiosDir.dir[idIndex].common.size)
697 {
698 phosphor::logging::log<phosphor::logging::level::ERR>(
699 "Offset is outside of range.");
700 return IPMI_CC_PARM_OUT_OF_RANGE;
701 }
702
703 size_t outSize =
704 (requestData->xferLength > mdrv2->smbiosDir.dir[idIndex].xferSize)
705 ? mdrv2->smbiosDir.dir[idIndex].xferSize
706 : requestData->xferLength;
707 if (outSize > UINT_MAX - requestData->xferOffset)
708 {
709 phosphor::logging::log<phosphor::logging::level::ERR>(
710 "Out size and offset are out of range");
711 return IPMI_CC_PARM_OUT_OF_RANGE;
712 }
713 if ((requestData->xferOffset + outSize) >
714 mdrv2->smbiosDir.dir[idIndex].common.size)
715 {
716 outSize =
717 mdrv2->smbiosDir.dir[idIndex].common.size - requestData->xferOffset;
718 }
719
720 responseData->xferLength = outSize;
721 if (responseData->xferLength > requestData->xferLength)
722 {
723 phosphor::logging::log<phosphor::logging::level::ERR>(
724 "Get data block unexpected error.");
725 return IPMI_CC_UNSPECIFIED_ERROR;
726 }
727
728 if ((requestData->xferOffset + outSize) >
729 UINT_MAX -
730 reinterpret_cast<size_t>(mdrv2->smbiosDir.dir[idIndex].dataStorage))
731 {
732 phosphor::logging::log<phosphor::logging::level::ERR>(
733 "Input data to calculate checksum is out of range");
734 return IPMI_CC_PARM_OUT_OF_RANGE;
735 }
736
737 uint32_t u32Checksum = mdrv2->calcChecksum32(
738 mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset,
739 outSize);
740 if (u32Checksum == invalidChecksum)
741 {
742 phosphor::logging::log<phosphor::logging::level::ERR>(
743 "Get data block failed - invalid checksum");
744 return IPMI_CC_OEM_INVALID_CHECKSUM;
745 }
746 responseData->checksum = u32Checksum;
747
748 *data_len = sizeof(responseData->xferLength) +
749 sizeof(responseData->checksum) + outSize;
750
751 if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
752 // than MAX_IPMI_BUFFER
753 {
754 phosphor::logging::log<phosphor::logging::level::ERR>(
755 "Data length send from service is invalid");
756 *data_len = 0;
757 return IPMI_CC_RESPONSE_ERROR;
758 }
759
760 std::copy(
761 &mdrv2->smbiosDir.dir[idIndex].dataStorage[requestData->xferOffset],
762 &mdrv2->smbiosDir.dir[idIndex]
763 .dataStorage[requestData->xferOffset + outSize],
764 responseData->data);
765
766 return IPMI_CC_OK;
767}
768
769ipmi_ret_t cmd_mdr2_send_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
770 ipmi_request_t request,
771 ipmi_response_t response,
772 ipmi_data_len_t data_len,
773 ipmi_context_t context)
774{
775 auto requestData =
776 reinterpret_cast<const MDRiiSendDataBlockRequest *>(request);
777
778 if (*data_len != sizeof(MDRiiSendDataBlockRequest))
779 {
780 *data_len = 0;
781 return IPMI_CC_REQ_DATA_LEN_INVALID;
782 }
783
784 *data_len = 0;
785
786 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
787
788 if (mdrv2 == nullptr)
789 {
790 mdrv2 = std::make_unique<MDRV2>();
791 }
792
793 int agentIndex = mdrv2->agentLookup(requestData->agentId);
794 if (agentIndex == -1)
795 {
796 phosphor::logging::log<phosphor::logging::level::ERR>(
797 "Unknown agent id",
798 phosphor::logging::entry("ID=%x", requestData->agentId));
799 return IPMI_CC_PARM_OUT_OF_RANGE;
800 }
801
802 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
803
804 if ((idIndex < 0) || (idIndex >= maxDirEntries))
805 {
806 phosphor::logging::log<phosphor::logging::level::ERR>(
807 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
808 return IPMI_CC_PARM_OUT_OF_RANGE;
809 }
810
811 if (mdrv2->smbiosIsUpdating(idIndex))
812 {
813 if (requestData->xferOffset > UINT_MAX - requestData->xferLength)
814 {
815 phosphor::logging::log<phosphor::logging::level::ERR>(
816 "Offset and length are out of range");
817 return IPMI_CC_PARM_OUT_OF_RANGE;
818 }
819 if (((requestData->xferOffset + requestData->xferLength) >
820 mdrv2->smbiosDir.dir[idIndex].maxDataSize) ||
821 ((requestData->xferOffset + requestData->xferLength) >
822 mdrv2->smbiosDir.dir[idIndex].common.dataSetSize))
823 {
824 phosphor::logging::log<phosphor::logging::level::ERR>(
825 "Send data block Invalid offset/length");
826 return IPMI_CC_REQUEST_DATA_FIELD_LENGTH_LIMIT_EXCEEDED;
827 }
828 if (reinterpret_cast<size_t>(
829 mdrv2->smbiosDir.dir[idIndex].dataStorage) >
830 UINT_MAX - requestData->xferOffset)
831 {
832 phosphor::logging::log<phosphor::logging::level::ERR>(
833 "Offset is out of range");
834 return IPMI_CC_PARM_OUT_OF_RANGE;
835 }
836 uint8_t *destAddr =
837 mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset;
838 uint8_t *sourceAddr = reinterpret_cast<uint8_t *>(mdrv2->area->vPtr);
839 uint32_t calcChecksum =
840 mdrv2->calcChecksum32(sourceAddr, requestData->xferLength);
841 if (calcChecksum != requestData->checksum)
842 {
843 phosphor::logging::log<phosphor::logging::level::ERR>(
844 "Send data block Invalid checksum");
845 return IPMI_CC_OEM_INVALID_CHECKSUM;
846 }
847 else
848 {
849 if (reinterpret_cast<size_t>(sourceAddr) >
850 UINT_MAX - requestData->xferLength)
851 {
852 phosphor::logging::log<phosphor::logging::level::ERR>(
853 "Length is out of range");
854 return IPMI_CC_PARM_OUT_OF_RANGE;
855 }
856 std::copy(sourceAddr, sourceAddr + requestData->xferLength,
857 destAddr);
858 }
859 }
860 else
861 {
862 phosphor::logging::log<phosphor::logging::level::ERR>(
863 "Send data block failed, other data is updating");
864 return IPMI_CC_DESTINATION_UNAVAILABLE;
865 }
866
867 return IPMI_CC_OK;
868}
869
870bool MDRV2::storeDatatoFlash(MDRSMBIOSHeader *mdrHdr, uint8_t *data)
871{
872 std::ofstream smbiosFile(mdrType2File,
873 std::ios_base::binary | std::ios_base::trunc);
874 if (!smbiosFile.good())
875 {
876 phosphor::logging::log<phosphor::logging::level::ERR>(
877 "Write data from flash error - Open MDRV2 table file failure");
878 return false;
879 }
880
881 try
882 {
883 smbiosFile.write(reinterpret_cast<char *>(mdrHdr),
884 sizeof(MDRSMBIOSHeader));
885 smbiosFile.write(reinterpret_cast<char *>(data), mdrHdr->dataSize);
886 }
887 catch (std::ofstream::failure &e)
888 {
889 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700890 "Write data from flash error - write data error",
891 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -0700892 return false;
893 }
894
895 return true;
896}
897
898void SharedMemoryArea::Initialize(uint32_t addr, uint32_t areaSize)
899{
900 int memDriver = 0;
901
902 // open mem driver for the system memory access
903 memDriver = open("/dev/vgasharedmem", O_RDONLY);
904 if (memDriver < 0)
905 {
906 phosphor::logging::log<phosphor::logging::level::ERR>(
907 "Cannot access mem driver");
908 throw std::system_error(EIO, std::generic_category());
909 }
910
911 // map the system memory
912 vPtr = mmap(NULL, // where to map to: don't mind
913 areaSize, // how many bytes ?
914 PROT_READ, // want to read and write
915 MAP_SHARED, // no copy on write
916 memDriver, // handle to /dev/mem
917 (physicalAddr & pageMask)); // hopefully the Text-buffer :-)
918
919 close(memDriver);
920 if (vPtr == MAP_FAILED)
921 {
922 phosphor::logging::log<phosphor::logging::level::ERR>(
923 "Failed to map share memory");
924 throw std::system_error(EIO, std::generic_category());
925 }
926 size = areaSize;
927 physicalAddr = addr;
928}
929
930bool MDRV2::smbiosUnlock(uint8_t index)
931{
932 bool ret;
933 switch (smbiosDir.dir[index].stage)
934 {
935 case MDR2SMBIOSStatusEnum::mdr2Updating:
936 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updated;
937 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
938
939 timer->stop();
940 smbiosDir.dir[index].lockHandle = 0;
941 ret = true;
942 break;
943
944 case MDR2SMBIOSStatusEnum::mdr2Updated:
945 case MDR2SMBIOSStatusEnum::mdr2Loaded:
946 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
947
948 timer->stop();
949
950 smbiosDir.dir[index].lockHandle = 0;
951 ret = true;
952 break;
953
954 default:
955 break;
956 }
957
958 return ret;
959}
960
961bool MDRV2::smbiosTryLock(uint8_t flag, uint8_t index, uint16_t *session,
962 uint16_t timeout)
963{
964 bool ret = false;
965 uint32_t u32Status = 0;
966
967 if (timeout == 0)
968 {
969 timeout = defaultTimeout;
970 }
971 std::chrono::microseconds usec(timeout * sysClock);
972
973 switch (smbiosDir.dir[index].stage)
974 {
975 case MDR2SMBIOSStatusEnum::mdr2Updating:
976 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
977 {
978 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
979 timer->start(usec);
980 lockIndex = index;
981
982 *session = getSessionHandle(&smbiosDir);
983 smbiosDir.dir[index].lockHandle = *session;
984 ret = true;
985 }
986 break;
987 case MDR2SMBIOSStatusEnum::mdr2Init:
988 if (flag)
989 {
990 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updating;
991 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
992 timer->start(usec);
993 lockIndex = index;
994
995 *session = getSessionHandle(&smbiosDir);
996 smbiosDir.dir[index].lockHandle = *session;
997 ret = true;
998 }
999 break;
1000
1001 case MDR2SMBIOSStatusEnum::mdr2Updated:
1002 case MDR2SMBIOSStatusEnum::mdr2Loaded:
1003 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
1004 {
1005 if (flag)
1006 {
1007 smbiosDir.dir[index].stage =
1008 MDR2SMBIOSStatusEnum::mdr2Updating;
1009 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
1010 }
1011 else
1012 {
1013 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
1014 }
1015
1016 timer->start(usec);
1017 lockIndex = index;
1018
1019 *session = getSessionHandle(&smbiosDir);
1020 smbiosDir.dir[index].lockHandle = *session;
1021 ret = true;
1022 }
1023 break;
1024
1025 default:
1026 break;
1027 }
1028 return ret;
1029}
1030
1031void MDRV2::timeoutHandler()
1032{
1033 smbiosUnlock(lockIndex);
1034 mdrv2->area.reset(nullptr);
1035}
1036
1037ipmi_ret_t cmd_mdr2_lock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1038 ipmi_request_t request, ipmi_response_t response,
1039 ipmi_data_len_t data_len, ipmi_context_t context)
1040{
1041 auto requestData = reinterpret_cast<const MDRiiLockDataRequest *>(request);
1042 auto responseData = reinterpret_cast<MDRiiLockDataResponse *>(response);
1043 uint16_t session = 0;
1044
1045 std::tuple<bool, uint8_t, uint16_t, uint32_t, uint32_t, uint32_t> res;
1046
1047 if (*data_len < sizeof(MDRiiLockDataRequest))
1048 {
1049 *data_len = 0;
1050 return IPMI_CC_REQ_DATA_LEN_INVALID;
1051 }
1052
1053 *data_len = 0;
1054
1055 if (mdrv2 == nullptr)
1056 {
1057 mdrv2 = std::make_unique<MDRV2>();
1058 }
1059
1060 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1061 if (agentIndex == -1)
1062 {
1063 phosphor::logging::log<phosphor::logging::level::ERR>(
1064 "Unknown agent id",
1065 phosphor::logging::entry("ID=%x", requestData->agentId));
1066 return IPMI_CC_PARM_OUT_OF_RANGE;
1067 }
1068
1069 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1070
1071 int idIndex =
1072 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
1073 sizeof(requestData->dataSetInfo.dataInfo), service);
1074
1075 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1076 {
1077 phosphor::logging::log<phosphor::logging::level::ERR>(
1078 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1079 return IPMI_CC_PARM_OUT_OF_RANGE;
1080 }
1081
1082 if (!mdrv2->smbiosTryLock(0, idIndex, &session, requestData->timeout))
1083 {
1084 phosphor::logging::log<phosphor::logging::level::ERR>(
1085 "Lock Data failed - cannot lock idIndex");
1086 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
1087 }
1088
1089 *data_len = sizeof(MDRiiLockDataResponse);
1090
1091 responseData->mdrVersion = mdr2Version;
1092 responseData->lockHandle = session;
1093 responseData->dataLength = mdrv2->smbiosDir.dir[idIndex].common.size;
1094 responseData->xferAddress = mdrv2->smbiosDir.dir[idIndex].xferBuff;
1095 responseData->xferLength = mdrv2->smbiosDir.dir[idIndex].xferSize;
1096
1097 return IPMI_CC_OK;
1098}
1099
1100ipmi_ret_t cmd_mdr2_unlock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1101 ipmi_request_t request,
1102 ipmi_response_t response,
1103 ipmi_data_len_t data_len,
1104 ipmi_context_t context)
1105{
1106 phosphor::logging::log<phosphor::logging::level::ERR>("unlock data");
1107 auto requestData =
1108 reinterpret_cast<const MDRiiUnlockDataRequest *>(request);
1109
1110 if (*data_len != sizeof(MDRiiUnlockDataRequest))
1111 {
1112 *data_len = 0;
1113 return IPMI_CC_REQ_DATA_LEN_INVALID;
1114 }
1115
1116 *data_len = 0;
1117
1118 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1119
1120 if (mdrv2 == nullptr)
1121 {
1122 mdrv2 = std::make_unique<MDRV2>();
1123 }
1124
1125 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1126 if (agentIndex == -1)
1127 {
1128 phosphor::logging::log<phosphor::logging::level::ERR>(
1129 "Unknown agent id",
1130 phosphor::logging::entry("ID=%x", requestData->agentId));
1131 return IPMI_CC_PARM_OUT_OF_RANGE;
1132 }
1133
1134 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
1135
1136 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1137 {
1138 phosphor::logging::log<phosphor::logging::level::ERR>(
1139 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1140 return IPMI_CC_PARM_OUT_OF_RANGE;
1141 }
1142
1143 if (!mdrv2->smbiosUnlock(idIndex))
1144 {
1145 phosphor::logging::log<phosphor::logging::level::ERR>(
1146 "Unlock Data failed - cannot unlock idIndex");
1147 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
1148 }
1149
1150 return IPMI_CC_OK;
1151}
1152
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001153/**
1154@brief This command is executed after POST BIOS to get the session info.
1155
1156@param - agentId, dataInfo, dataLength, xferAddress, xferLength, timeout.
1157
1158@return xferStartAck and session on success.
1159**/
1160ipmi::RspType<uint8_t, uint16_t>
1161 cmd_mdr2_data_start(uint16_t agentId, std::array<uint8_t, 16> dataInfo,
1162 uint32_t dataLength, uint32_t xferAddress,
1163 uint32_t xferLength, uint16_t timeout)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001164{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001165 uint16_t session = 0;
1166
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001167 if (dataLength > smbiosTableStorageSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001168 {
1169 phosphor::logging::log<phosphor::logging::level::ERR>(
1170 "Requested data length is out of SMBIOS Table storage size.");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001171 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001172 }
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001173 if ((xferLength + xferAddress) > mdriiSMSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001174 {
1175 phosphor::logging::log<phosphor::logging::level::ERR>(
1176 "Invalid data address and size");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001177 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001178 }
1179
1180 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1181
1182 if (mdrv2 == nullptr)
1183 {
1184 mdrv2 = std::make_unique<MDRV2>();
1185 }
1186
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001187 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001188 if (agentIndex == -1)
1189 {
1190 phosphor::logging::log<phosphor::logging::level::ERR>(
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001191 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1192 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001193 }
1194
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001195 int idIndex = mdrv2->findDataId(dataInfo.data(), sizeof(dataInfo), service);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001196
1197 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1198 {
1199 phosphor::logging::log<phosphor::logging::level::ERR>(
1200 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001201 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001202 }
1203
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001204 if (mdrv2->smbiosTryLock(1, idIndex, &session, timeout))
Vernon Mauerya3702c12019-05-22 13:20:59 -07001205 {
1206 try
1207 {
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001208 mdrv2->area =
1209 std::make_unique<SharedMemoryArea>(xferAddress, xferLength);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001210 }
1211 catch (const std::system_error &e)
1212 {
1213 mdrv2->smbiosUnlock(idIndex);
1214 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001215 "Unable to access share memory",
1216 phosphor::logging::entry("ERROR=%s", e.what()));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001217 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001218 }
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001219 mdrv2->smbiosDir.dir[idIndex].common.size = dataLength;
Vernon Mauerya3702c12019-05-22 13:20:59 -07001220 mdrv2->smbiosDir.dir[idIndex].lockHandle = session;
1221 if (-1 ==
1222 mdrv2->syncDirCommonData(
1223 idIndex, mdrv2->smbiosDir.dir[idIndex].common.size, service))
1224 {
1225 phosphor::logging::log<phosphor::logging::level::ERR>(
1226 "Unable to sync data to service");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001227 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001228 }
1229 }
1230 else
1231 {
1232 phosphor::logging::log<phosphor::logging::level::ERR>(
1233 "Canot lock smbios");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001234 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001235 }
1236
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001237 static constexpr uint8_t xferStartAck = 1;
Vernon Mauerya3702c12019-05-22 13:20:59 -07001238
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001239 return ipmi::responseSuccess(xferStartAck, session);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001240}
1241
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001242/**
1243@brief This command is executed to close the session.
1244
1245@param - agentId, lockHandle.
1246
1247@return completion code on success.
1248**/
1249ipmi::RspType<> cmd_mdr2_data_done(uint16_t agentId, uint16_t lockHandle)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001250{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001251
1252 if (mdrv2 == nullptr)
1253 {
1254 mdrv2 = std::make_unique<MDRV2>();
1255 }
1256
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001257 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001258 if (agentIndex == -1)
1259 {
1260 phosphor::logging::log<phosphor::logging::level::ERR>(
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001261 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1262 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001263 }
1264
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001265 int idIndex = mdrv2->findLockHandle(lockHandle);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001266
1267 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1268 {
1269 phosphor::logging::log<phosphor::logging::level::ERR>(
1270 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001271 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001272 }
1273
1274 if (!mdrv2->smbiosUnlock(idIndex))
1275 {
1276 phosphor::logging::log<phosphor::logging::level::ERR>(
1277 "Send data done failed - cannot unlock idIndex");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001278 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001279 }
1280
1281 mdrv2->area.reset(nullptr);
1282 MDRSMBIOSHeader mdr2Smbios;
1283 mdr2Smbios.mdrType = mdrTypeII;
1284 mdr2Smbios.dirVer = mdrv2->smbiosDir.dir[0].common.dataVersion;
1285 mdr2Smbios.timestamp = mdrv2->smbiosDir.dir[0].common.timestamp;
1286 mdr2Smbios.dataSize = mdrv2->smbiosDir.dir[0].common.size;
1287
1288 if (access(smbiosPath, 0) == -1)
1289 {
1290 int flag = mkdir(smbiosPath, S_IRWXU);
1291 if (flag != 0)
1292 {
1293 phosphor::logging::log<phosphor::logging::level::ERR>(
1294 "create folder failed for writting smbios file");
1295 }
1296 }
1297 if (!mdrv2->storeDatatoFlash(
1298 &mdr2Smbios, mdrv2->smbiosDir.dir[smbiosDirIndex].dataStorage))
1299 {
1300 phosphor::logging::log<phosphor::logging::level::ERR>(
1301 "MDR2 Store data to flash failed");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001302 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001303 }
Vernon Mauerya3702c12019-05-22 13:20:59 -07001304 bool status = false;
1305 std::string service = ipmi::getService(bus, mdrv2Interface, mdrv2Path);
1306 sdbusplus::message::message method = bus.new_method_call(
1307 service.c_str(), mdrv2Path, mdrv2Interface, "AgentSynchronizeData");
1308
1309 try
1310 {
1311 sdbusplus::message::message reply = bus.call(method);
1312 reply.read(status);
1313 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001314 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001315 {
1316 phosphor::logging::log<phosphor::logging::level::ERR>(
1317 "Error Sync data with service",
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001318 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -07001319 phosphor::logging::entry("SERVICE=%s", service.c_str()),
1320 phosphor::logging::entry("PATH=%s", mdrv2Path));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001321 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001322 }
1323
1324 if (!status)
1325 {
1326 phosphor::logging::log<phosphor::logging::level::ERR>(
1327 "Sync data with service failure");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001328 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001329 }
1330
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001331 return ipmi::responseSuccess();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001332}
1333
1334static void register_netfn_smbiosmdrv2_functions(void)
1335{
1336 // MDR V2 Command
1337 // <Get MDRII Status Command>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001338 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1339 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_AGENT_STATUS,
1340 ipmi::Privilege::Operator, mdr2AgentStatus);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001341
1342 // <Get MDRII Directory Command>
1343 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1344 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DIR, NULL,
1345 cmd_mdr2_get_dir, PRIVILEGE_OPERATOR);
1346
1347 // <Send MDRII Directory Command>
1348 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1349 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DIR, NULL,
1350 cmd_mdr2_send_dir, PRIVILEGE_OPERATOR);
1351
1352 // <Get MDRII Data Info Command>
1353 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1354 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_INFO,
1355 NULL, cmd_mdr2_get_data_info, PRIVILEGE_OPERATOR);
1356
1357 // <Send MDRII Info Offer>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001358 ipmi::registerHandler(
1359 ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1360 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO_OFFER,
1361 ipmi::Privilege::Operator, mdr2DataInfoOffer);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001362
1363 // <Send MDRII Data Info>
1364 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1365 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO,
1366 NULL, cmd_mdr2_send_data_info, PRIVILEGE_OPERATOR);
1367
1368 // <Get MDRII Data Block Command>
1369 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1370 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_BLOCK,
1371 NULL, cmd_mdr2_get_data_block, PRIVILEGE_OPERATOR);
1372
1373 // <Send MDRII Data Block>
1374 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1375 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_BLOCK,
1376 NULL, cmd_mdr2_send_data_block, PRIVILEGE_OPERATOR);
1377
1378 // <Lock MDRII Data Command>
1379 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1380 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_LOCK_DATA, NULL,
1381 cmd_mdr2_lock_data, PRIVILEGE_OPERATOR);
1382
1383 // <Unlock MDRII Data Command>
1384 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1385 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_UNLOCK_DATA,
1386 NULL, cmd_mdr2_unlock_data, PRIVILEGE_OPERATOR);
1387
1388 // <Send MDRII Data Start>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001389 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1390 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_START,
1391 ipmi::Privilege::Operator, cmd_mdr2_data_start);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001392
1393 // <Send MDRII Data Done>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001394 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1395 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_DONE,
1396 ipmi::Privilege::Operator, cmd_mdr2_data_done);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001397}