blob: 193b2f573086b65cf9791020d2f1026c3a9f3242 [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>
Vernon Mauerya3702c12019-05-22 13:20:59 -070030#include <sdbusplus/message/types.hpp>
31#include <smbiosmdrv2handler.hpp>
32#include <string>
33#include <vector>
34#include <xyz/openbmc_project/Common/error.hpp>
Vernon Mauerya3702c12019-05-22 13:20:59 -070035
36std::unique_ptr<MDRV2> mdrv2 = nullptr;
37
Vernon Mauerya3702c12019-05-22 13:20:59 -070038static void register_netfn_smbiosmdrv2_functions() __attribute__((constructor));
Vernon Mauerya3702c12019-05-22 13:20:59 -070039
40int MDRV2::agentLookup(const uint16_t &agentId)
41{
42 int agentIndex = -1;
43
44 if (lastAgentId == agentId)
45 {
46 return lastAgentIndex;
47 }
48
49 if (agentId == smbiosAgentId)
50 {
51 return firstAgentIndex;
52 }
53
54 return agentIndex;
55}
56
57int MDRV2::sdplusMdrv2GetProperty(const std::string &name,
58 sdbusplus::message::variant<uint8_t> &value,
59 const std::string &service)
60{
Vernon Mauery15419dd2019-05-24 09:40:30 -070061 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
Vernon Mauerya3702c12019-05-22 13:20:59 -070062 sdbusplus::message::message method =
Vernon Mauery15419dd2019-05-24 09:40:30 -070063 bus->new_method_call(service.c_str(), mdrv2Path, dbusProperties, "Get");
Vernon Mauerya3702c12019-05-22 13:20:59 -070064 method.append(mdrv2Interface, name);
65
Vernon Mauery15419dd2019-05-24 09:40:30 -070066 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -070067
68 try
69 {
Vernon Mauery15419dd2019-05-24 09:40:30 -070070 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -070071 reply.read(value);
72 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -070073 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -070074 {
75 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -070076 "Error get property, sdbusplus call failed",
77 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -070078 return -1;
79 }
80
81 return 0;
82}
83
84int MDRV2::syncDirCommonData(uint8_t idIndex, uint32_t size,
85 const std::string &service)
86{
87 std::vector<uint32_t> commonData;
Vernon Mauery15419dd2019-05-24 09:40:30 -070088 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
Vernon Mauerya3702c12019-05-22 13:20:59 -070089 sdbusplus::message::message method =
Vernon Mauery15419dd2019-05-24 09:40:30 -070090 bus->new_method_call(service.c_str(), mdrv2Path, mdrv2Interface,
91 "SynchronizeDirectoryCommonData");
Vernon Mauerya3702c12019-05-22 13:20:59 -070092 method.append(idIndex, size);
93
94 try
95 {
Vernon Mauery15419dd2019-05-24 09:40:30 -070096 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -070097 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
Vernon Mauery15419dd2019-05-24 09:40:30 -0700132 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
133 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700134 service.c_str(), mdrv2Path, mdrv2Interface, "FindIdIndex");
135 std::vector<uint8_t> info;
136 info.resize(len);
137 std::copy(dataInfo, dataInfo + len, info.data());
138 method.append(info);
139
140 try
141 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700142 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700143 reply.read(idIndex);
144 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700145 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700146 {
147 phosphor::logging::log<phosphor::logging::level::ERR>(
148 "Error find id index",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700149 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700150 phosphor::logging::entry("SERVICE=%s", service.c_str()),
151 phosphor::logging::entry("PATH=%s", mdrv2Path));
152 return -1;
153 }
154
155 return idIndex;
156}
157
158uint16_t MDRV2::getSessionHandle(Mdr2DirStruct *dir)
159{
160 if (dir == NULL)
161 {
162 phosphor::logging::log<phosphor::logging::level::ERR>(
163 "Empty dir point");
164 return 0;
165 }
166 dir->sessionHandle++;
167 if (dir->sessionHandle == 0)
168 {
169 dir->sessionHandle = 1;
170 }
171
172 return dir->sessionHandle;
173}
174
175int MDRV2::findLockHandle(const uint16_t &lockHandle)
176{
177 int idIndex = -1;
178
179 for (int index = 0; index < smbiosDir.dirEntries; index++)
180 {
181 if (lockHandle == smbiosDir.dir[index].lockHandle)
182 {
183 return index;
184 }
185 }
186
187 return idIndex;
188}
189
190bool MDRV2::smbiosIsUpdating(uint8_t index)
191{
192 if (index > maxDirEntries)
193 {
194 return false;
195 }
196 if (smbiosDir.dir[index].stage == MDR2SMBIOSStatusEnum::mdr2Updating)
197 {
198 return true;
199 }
200
201 return false;
202}
203
204uint32_t MDRV2::calcChecksum32(uint8_t *buf, uint32_t len)
205{
206 uint32_t sum = 0;
207
208 if (buf == nullptr)
209 {
210 return invalidChecksum;
211 }
212
213 for (uint32_t index = 0; index < len; index++)
214 {
215 sum += buf[index];
216 }
217
218 return sum;
219}
220
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000221/** @brief implements mdr2 agent status command
222 * @param agentId
223 * @param dirVersion
224 *
225 * @returns IPMI completion code plus response data
226 * - mdrVersion
227 * - agentVersion
228 * - dirVersion
229 * - dirEntries
230 * - dataRequest
231 */
232ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t, uint8_t>
233 mdr2AgentStatus(uint16_t agentId, uint8_t dirVersion)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700234{
Vernon Mauerya3702c12019-05-22 13:20:59 -0700235 if (mdrv2 == nullptr)
236 {
237 mdrv2 = std::make_unique<MDRV2>();
238 }
239
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000240 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700241 if (agentIndex == -1)
242 {
243 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000244 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
245 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700246 }
247
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000248 constexpr uint8_t mdrVersion = mdr2Version;
249 constexpr uint8_t agentVersion = smbiosAgentVersion;
250 uint8_t dirVersionResp = mdrv2->smbiosDir.dirVersion;
251 uint8_t dirEntries = mdrv2->smbiosDir.dirEntries;
252 uint8_t dataRequest;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700253
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000254 if (mdrv2->smbiosDir.remoteDirVersion != dirVersion)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700255 {
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000256 mdrv2->smbiosDir.remoteDirVersion = dirVersion;
257 dataRequest =
Vernon Mauerya3702c12019-05-22 13:20:59 -0700258 static_cast<uint8_t>(DirDataRequestEnum::dirDataRequested);
259 }
260 else
261 {
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000262 dataRequest =
Vernon Mauerya3702c12019-05-22 13:20:59 -0700263 static_cast<uint8_t>(DirDataRequestEnum::dirDataNotRequested);
264 }
265
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000266 return ipmi::responseSuccess(mdrVersion, agentVersion, dirVersionResp,
267 dirEntries, dataRequest);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700268}
269
270ipmi_ret_t cmd_mdr2_get_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
271 ipmi_request_t request, ipmi_response_t response,
272 ipmi_data_len_t data_len, ipmi_context_t context)
273{
274 auto requestData = reinterpret_cast<const MDRiiGetDirRequest *>(request);
275 auto dataOut = reinterpret_cast<uint8_t *>(response);
276 std::vector<uint8_t> dirInfo;
277
278 if (*data_len != sizeof(MDRiiGetDirRequest))
279 {
280 *data_len = 0;
281 return IPMI_CC_REQ_DATA_LEN_INVALID;
282 }
283
284 *data_len = 0;
285
Vernon Mauery15419dd2019-05-24 09:40:30 -0700286 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
287 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700288
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 }
Vernon Mauery8166c8d2019-05-23 11:22:30 -0700310 if (requestData->dirIndex > std::get<uint8_t>(value))
Vernon Mauerya3702c12019-05-22 13:20:59 -0700311 {
312 return IPMI_CC_PARM_OUT_OF_RANGE;
313 }
314
Vernon Mauery15419dd2019-05-24 09:40:30 -0700315 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700316 service.c_str(), mdrv2Path, mdrv2Interface, "GetDirectoryInformation");
317
318 method.append(requestData->dirIndex);
319
320 try
321 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700322 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700323 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
Vernon Mauery15419dd2019-05-24 09:40:30 -0700375 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
376 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700377
378 if (mdrv2 == nullptr)
379 {
380 mdrv2 = std::make_unique<MDRV2>();
381 }
382
383 int agentIndex = mdrv2->agentLookup(requestData->agentId);
384 if (agentIndex == -1)
385 {
386 phosphor::logging::log<phosphor::logging::level::ERR>(
387 "Unknown agent id",
388 phosphor::logging::entry("ID=%x", requestData->agentId));
389 return IPMI_CC_PARM_OUT_OF_RANGE;
390 }
391
392 if ((requestData->dirIndex + requestData->returnedEntries) > maxDirEntries)
393 {
394 phosphor::logging::log<phosphor::logging::level::ERR>(
395 "Too many directory entries");
396 return IPMI_CC_STORGE_LEAK;
397 }
398
Vernon Mauery15419dd2019-05-24 09:40:30 -0700399 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700400 service.c_str(), mdrv2Path, mdrv2Interface, "SendDirectoryInformation");
401 method.append(requestData->dirVersion, requestData->dirIndex,
402 requestData->returnedEntries, requestData->remainingEntries);
403 uint8_t *reqPoint;
404 for (int index = 0; index < requestData->returnedEntries; index++)
405 {
406 reqPoint = (uint8_t *)&(requestData->data[index]);
407 std::copy(reqPoint, sizeof(Mdr2DirEntry) + reqPoint, idVector.data());
408 }
409 method.append(idVector);
410
411 try
412 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700413 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700414 reply.read(teminate);
415 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700416 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700417 {
418 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700419 "Error send dir", phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700420 phosphor::logging::entry("SERVICE=%s", service.c_str()),
421 phosphor::logging::entry("PATH=%s", mdrv2Path));
422 return IPMI_CC_RESPONSE_ERROR;
423 }
424
425 *data_len = 1;
426 if (teminate == false)
427 *(static_cast<uint8_t *>(response)) = 0;
428 else
429 *(static_cast<uint8_t *>(response)) = 1;
430 return IPMI_CC_OK;
431}
432
433ipmi_ret_t cmd_mdr2_get_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
434 ipmi_request_t request,
435 ipmi_response_t response,
436 ipmi_data_len_t data_len,
437 ipmi_context_t context)
438{
439 auto requestData =
440 reinterpret_cast<const MDRiiGetDataInfoRequest *>(request);
441 auto dataOut = reinterpret_cast<uint8_t *>(response);
442 std::vector<uint8_t> res;
443
444 if (*data_len < sizeof(MDRiiGetDataInfoRequest))
445 {
446 *data_len = 0;
447 return IPMI_CC_REQ_DATA_LEN_INVALID;
448 }
449
450 *data_len = 0;
451
Vernon Mauery15419dd2019-05-24 09:40:30 -0700452 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
453 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700454
455 if (mdrv2 == nullptr)
456 {
457 mdrv2 = std::make_unique<MDRV2>();
458 }
459
460 int agentIndex = mdrv2->agentLookup(requestData->agentId);
461 if (agentIndex == -1)
462 {
463 phosphor::logging::log<phosphor::logging::level::ERR>(
464 "Unknown agent id",
465 phosphor::logging::entry("ID=%x", requestData->agentId));
466 return IPMI_CC_PARM_OUT_OF_RANGE;
467 }
468
469 int idIndex =
470 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
471 sizeof(requestData->dataSetInfo.dataInfo), service);
472
473 if ((idIndex < 0) || (idIndex >= maxDirEntries))
474 {
475 phosphor::logging::log<phosphor::logging::level::ERR>(
476 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
477 return IPMI_CC_PARM_OUT_OF_RANGE;
478 }
479
Vernon Mauery15419dd2019-05-24 09:40:30 -0700480 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700481 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataInformation");
482
483 method.append(idIndex);
484
485 try
486 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700487 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700488 reply.read(res);
489 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700490 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700491 {
492 phosphor::logging::log<phosphor::logging::level::ERR>(
493 "Error get data info",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700494 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700495 phosphor::logging::entry("SERVICE=%s", service.c_str()),
496 phosphor::logging::entry("PATH=%s", mdrv2Path));
497 return IPMI_CC_RESPONSE_ERROR;
498 }
499
500 if (res.size() != sizeof(MDRiiGetDataInfoResponse))
501 {
502 phosphor::logging::log<phosphor::logging::level::ERR>(
503 "Get data info response length not invalid");
504 return IPMI_CC_UNSPECIFIED_ERROR;
505 }
506 *data_len = static_cast<size_t>(res.size());
507 std::copy(&res[0], &res[*data_len], dataOut);
508
509 return IPMI_CC_OK;
510}
511
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000512/** @brief implements mdr2 data info offer command
513 * @param agentId - Offer a agent ID to get the "Data Set ID"
514 *
515 * @returns IPMI completion code plus response data
516 * - dataInfo
517 */
518ipmi::RspType<std::vector<uint8_t>> mdr2DataInfoOffer(uint16_t agentId)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700519{
Vernon Mauery15419dd2019-05-24 09:40:30 -0700520 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
521 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700522
523 if (mdrv2 == nullptr)
524 {
525 mdrv2 = std::make_unique<MDRV2>();
526 }
527
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000528 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700529 if (agentIndex == -1)
530 {
531 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000532 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
533 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700534 }
535
Vernon Mauery15419dd2019-05-24 09:40:30 -0700536 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700537 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataOffer");
538
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000539 std::vector<uint8_t> dataInfo;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700540 try
541 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700542 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700543 reply.read(dataInfo);
544 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700545 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700546 {
547 phosphor::logging::log<phosphor::logging::level::ERR>(
548 "Error send data info offer",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700549 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700550 phosphor::logging::entry("SERVICE=%s", service.c_str()),
551 phosphor::logging::entry("PATH=%s", mdrv2Path));
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000552 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700553 }
554
555 if (dataInfo.size() != sizeof(MDRiiOfferDataInfoResponse))
556 {
557 phosphor::logging::log<phosphor::logging::level::ERR>(
558 "Error send data info offer, return length invalid");
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000559 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700560 }
561
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000562 return ipmi::responseSuccess(dataInfo);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700563}
564
565ipmi_ret_t cmd_mdr2_send_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
566 ipmi_request_t request,
567 ipmi_response_t response,
568 ipmi_data_len_t data_len,
569 ipmi_context_t context)
570{
571 auto requestData =
572 reinterpret_cast<const MDRiiSendDataInfoRequest *>(request);
573 bool entryChanged = true;
574
575 if (*data_len != sizeof(MDRiiSendDataInfoRequest))
576 {
577 *data_len = 0;
578 return IPMI_CC_REQ_DATA_LEN_INVALID;
579 }
580
581 *data_len = 0;
582
583 if (requestData->dataLength > smbiosTableStorageSize)
584 {
585 phosphor::logging::log<phosphor::logging::level::ERR>(
586 "Requested data length is out of SMBIOS Table storage size.");
587 return IPMI_CC_PARM_OUT_OF_RANGE;
588 }
589
Vernon Mauery15419dd2019-05-24 09:40:30 -0700590 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
591 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700592
593 if (mdrv2 == nullptr)
594 {
595 mdrv2 = std::make_unique<MDRV2>();
596 }
597
598 int agentIndex = mdrv2->agentLookup(requestData->agentId);
599 if (agentIndex == -1)
600 {
601 phosphor::logging::log<phosphor::logging::level::ERR>(
602 "Unknown agent id",
603 phosphor::logging::entry("ID=%x", requestData->agentId));
604 return IPMI_CC_PARM_OUT_OF_RANGE;
605 }
606
607 int idIndex =
608 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
609 sizeof(requestData->dataSetInfo.dataInfo), service);
610
611 if ((idIndex < 0) || (idIndex >= maxDirEntries))
612 {
613 phosphor::logging::log<phosphor::logging::level::ERR>(
614 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
615 return IPMI_CC_PARM_OUT_OF_RANGE;
616 }
617
Vernon Mauery15419dd2019-05-24 09:40:30 -0700618 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700619 service.c_str(), mdrv2Path, mdrv2Interface, "SendDataInformation");
620
621 method.append((uint8_t)idIndex, requestData->validFlag,
622 requestData->dataLength, requestData->dataVersion,
623 requestData->timeStamp);
624
625 try
626 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700627 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700628 reply.read(entryChanged);
629 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700630 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700631 {
632 phosphor::logging::log<phosphor::logging::level::ERR>(
633 "Error send data info",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700634 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700635 phosphor::logging::entry("SERVICE=%s", service.c_str()),
636 phosphor::logging::entry("PATH=%s", mdrv2Path));
637 return IPMI_CC_RESPONSE_ERROR;
638 }
639
640 *data_len = 1;
641
642 if (entryChanged)
643 {
644 *(static_cast<uint8_t *>(response)) = 1;
645 }
646 else
647 {
648 *(static_cast<uint8_t *>(response)) = 0;
649 }
650
651 return IPMI_CC_OK;
652}
653
654ipmi_ret_t cmd_mdr2_get_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
655 ipmi_request_t request,
656 ipmi_response_t response,
657 ipmi_data_len_t data_len,
658 ipmi_context_t context)
659{
660 auto requestData =
661 reinterpret_cast<const MDRiiGetDataBlockRequest *>(request);
662 auto responseData = reinterpret_cast<MDRiiGetDataBlockResponse *>(response);
663 std::tuple<uint8_t, uint32_t, uint32_t, std::vector<uint8_t>> res;
664 std::vector<uint8_t> resData;
665 uint8_t status = 1;
666
667 if (*data_len != sizeof(MDRiiGetDataBlockRequest))
668 {
669 *data_len = 0;
670 return IPMI_CC_REQ_DATA_LEN_INVALID;
671 }
672
673 *data_len = 0;
674
Vernon Mauerya3702c12019-05-22 13:20:59 -0700675 if (mdrv2 == nullptr)
676 {
677 mdrv2 = std::make_unique<MDRV2>();
678 }
679
680 int agentIndex = mdrv2->agentLookup(requestData->agentId);
681 if (agentIndex == -1)
682 {
683 phosphor::logging::log<phosphor::logging::level::ERR>(
684 "Unknown agent id",
685 phosphor::logging::entry("ID=%x", requestData->agentId));
686 return IPMI_CC_PARM_OUT_OF_RANGE;
687 }
688
689 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
690
691 if ((idIndex < 0) || (idIndex >= maxDirEntries))
692 {
693 phosphor::logging::log<phosphor::logging::level::ERR>(
694 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
695 return IPMI_CC_PARM_OUT_OF_RANGE;
696 }
697
698 if (requestData->xferOffset >= mdrv2->smbiosDir.dir[idIndex].common.size)
699 {
700 phosphor::logging::log<phosphor::logging::level::ERR>(
701 "Offset is outside of range.");
702 return IPMI_CC_PARM_OUT_OF_RANGE;
703 }
704
705 size_t outSize =
706 (requestData->xferLength > mdrv2->smbiosDir.dir[idIndex].xferSize)
707 ? mdrv2->smbiosDir.dir[idIndex].xferSize
708 : requestData->xferLength;
709 if (outSize > UINT_MAX - requestData->xferOffset)
710 {
711 phosphor::logging::log<phosphor::logging::level::ERR>(
712 "Out size and offset are out of range");
713 return IPMI_CC_PARM_OUT_OF_RANGE;
714 }
715 if ((requestData->xferOffset + outSize) >
716 mdrv2->smbiosDir.dir[idIndex].common.size)
717 {
718 outSize =
719 mdrv2->smbiosDir.dir[idIndex].common.size - requestData->xferOffset;
720 }
721
722 responseData->xferLength = outSize;
723 if (responseData->xferLength > requestData->xferLength)
724 {
725 phosphor::logging::log<phosphor::logging::level::ERR>(
726 "Get data block unexpected error.");
727 return IPMI_CC_UNSPECIFIED_ERROR;
728 }
729
730 if ((requestData->xferOffset + outSize) >
731 UINT_MAX -
732 reinterpret_cast<size_t>(mdrv2->smbiosDir.dir[idIndex].dataStorage))
733 {
734 phosphor::logging::log<phosphor::logging::level::ERR>(
735 "Input data to calculate checksum is out of range");
736 return IPMI_CC_PARM_OUT_OF_RANGE;
737 }
738
739 uint32_t u32Checksum = mdrv2->calcChecksum32(
740 mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset,
741 outSize);
742 if (u32Checksum == invalidChecksum)
743 {
744 phosphor::logging::log<phosphor::logging::level::ERR>(
745 "Get data block failed - invalid checksum");
746 return IPMI_CC_OEM_INVALID_CHECKSUM;
747 }
748 responseData->checksum = u32Checksum;
749
750 *data_len = sizeof(responseData->xferLength) +
751 sizeof(responseData->checksum) + outSize;
752
753 if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
754 // than MAX_IPMI_BUFFER
755 {
756 phosphor::logging::log<phosphor::logging::level::ERR>(
757 "Data length send from service is invalid");
758 *data_len = 0;
759 return IPMI_CC_RESPONSE_ERROR;
760 }
761
762 std::copy(
763 &mdrv2->smbiosDir.dir[idIndex].dataStorage[requestData->xferOffset],
764 &mdrv2->smbiosDir.dir[idIndex]
765 .dataStorage[requestData->xferOffset + outSize],
766 responseData->data);
767
768 return IPMI_CC_OK;
769}
770
771ipmi_ret_t cmd_mdr2_send_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
772 ipmi_request_t request,
773 ipmi_response_t response,
774 ipmi_data_len_t data_len,
775 ipmi_context_t context)
776{
777 auto requestData =
778 reinterpret_cast<const MDRiiSendDataBlockRequest *>(request);
779
780 if (*data_len != sizeof(MDRiiSendDataBlockRequest))
781 {
782 *data_len = 0;
783 return IPMI_CC_REQ_DATA_LEN_INVALID;
784 }
785
786 *data_len = 0;
787
Vernon Mauerya3702c12019-05-22 13:20:59 -0700788 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
Vernon Mauery15419dd2019-05-24 09:40:30 -07001069 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1070 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001071
1072 int idIndex =
1073 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
1074 sizeof(requestData->dataSetInfo.dataInfo), service);
1075
1076 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1077 {
1078 phosphor::logging::log<phosphor::logging::level::ERR>(
1079 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1080 return IPMI_CC_PARM_OUT_OF_RANGE;
1081 }
1082
1083 if (!mdrv2->smbiosTryLock(0, idIndex, &session, requestData->timeout))
1084 {
1085 phosphor::logging::log<phosphor::logging::level::ERR>(
1086 "Lock Data failed - cannot lock idIndex");
1087 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
1088 }
1089
1090 *data_len = sizeof(MDRiiLockDataResponse);
1091
1092 responseData->mdrVersion = mdr2Version;
1093 responseData->lockHandle = session;
1094 responseData->dataLength = mdrv2->smbiosDir.dir[idIndex].common.size;
1095 responseData->xferAddress = mdrv2->smbiosDir.dir[idIndex].xferBuff;
1096 responseData->xferLength = mdrv2->smbiosDir.dir[idIndex].xferSize;
1097
1098 return IPMI_CC_OK;
1099}
1100
1101ipmi_ret_t cmd_mdr2_unlock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1102 ipmi_request_t request,
1103 ipmi_response_t response,
1104 ipmi_data_len_t data_len,
1105 ipmi_context_t context)
1106{
1107 phosphor::logging::log<phosphor::logging::level::ERR>("unlock data");
1108 auto requestData =
1109 reinterpret_cast<const MDRiiUnlockDataRequest *>(request);
1110
1111 if (*data_len != sizeof(MDRiiUnlockDataRequest))
1112 {
1113 *data_len = 0;
1114 return IPMI_CC_REQ_DATA_LEN_INVALID;
1115 }
1116
1117 *data_len = 0;
1118
Vernon Mauerya3702c12019-05-22 13:20:59 -07001119 if (mdrv2 == nullptr)
1120 {
1121 mdrv2 = std::make_unique<MDRV2>();
1122 }
1123
1124 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1125 if (agentIndex == -1)
1126 {
1127 phosphor::logging::log<phosphor::logging::level::ERR>(
1128 "Unknown agent id",
1129 phosphor::logging::entry("ID=%x", requestData->agentId));
1130 return IPMI_CC_PARM_OUT_OF_RANGE;
1131 }
1132
1133 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
1134
1135 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1136 {
1137 phosphor::logging::log<phosphor::logging::level::ERR>(
1138 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1139 return IPMI_CC_PARM_OUT_OF_RANGE;
1140 }
1141
1142 if (!mdrv2->smbiosUnlock(idIndex))
1143 {
1144 phosphor::logging::log<phosphor::logging::level::ERR>(
1145 "Unlock Data failed - cannot unlock idIndex");
1146 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
1147 }
1148
1149 return IPMI_CC_OK;
1150}
1151
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001152/**
1153@brief This command is executed after POST BIOS to get the session info.
1154
1155@param - agentId, dataInfo, dataLength, xferAddress, xferLength, timeout.
1156
1157@return xferStartAck and session on success.
1158**/
1159ipmi::RspType<uint8_t, uint16_t>
1160 cmd_mdr2_data_start(uint16_t agentId, std::array<uint8_t, 16> dataInfo,
1161 uint32_t dataLength, uint32_t xferAddress,
1162 uint32_t xferLength, uint16_t timeout)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001163{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001164 uint16_t session = 0;
1165
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001166 if (dataLength > smbiosTableStorageSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001167 {
1168 phosphor::logging::log<phosphor::logging::level::ERR>(
1169 "Requested data length is out of SMBIOS Table storage size.");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001170 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001171 }
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001172 if ((xferLength + xferAddress) > mdriiSMSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001173 {
1174 phosphor::logging::log<phosphor::logging::level::ERR>(
1175 "Invalid data address and size");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001176 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001177 }
1178
Vernon Mauery15419dd2019-05-24 09:40:30 -07001179 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1180 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001181
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;
Vernon Mauery15419dd2019-05-24 09:40:30 -07001305 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1306 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
1307 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -07001308 service.c_str(), mdrv2Path, mdrv2Interface, "AgentSynchronizeData");
1309
1310 try
1311 {
Vernon Mauery15419dd2019-05-24 09:40:30 -07001312 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001313 reply.read(status);
1314 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001315 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001316 {
1317 phosphor::logging::log<phosphor::logging::level::ERR>(
1318 "Error Sync data with service",
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001319 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -07001320 phosphor::logging::entry("SERVICE=%s", service.c_str()),
1321 phosphor::logging::entry("PATH=%s", mdrv2Path));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001322 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001323 }
1324
1325 if (!status)
1326 {
1327 phosphor::logging::log<phosphor::logging::level::ERR>(
1328 "Sync data with service failure");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001329 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001330 }
1331
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001332 return ipmi::responseSuccess();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001333}
1334
1335static void register_netfn_smbiosmdrv2_functions(void)
1336{
1337 // MDR V2 Command
1338 // <Get MDRII Status Command>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001339 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1340 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_AGENT_STATUS,
1341 ipmi::Privilege::Operator, mdr2AgentStatus);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001342
1343 // <Get MDRII Directory Command>
1344 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1345 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DIR, NULL,
1346 cmd_mdr2_get_dir, PRIVILEGE_OPERATOR);
1347
1348 // <Send MDRII Directory Command>
1349 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1350 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DIR, NULL,
1351 cmd_mdr2_send_dir, PRIVILEGE_OPERATOR);
1352
1353 // <Get MDRII Data Info Command>
1354 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1355 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_INFO,
1356 NULL, cmd_mdr2_get_data_info, PRIVILEGE_OPERATOR);
1357
1358 // <Send MDRII Info Offer>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001359 ipmi::registerHandler(
1360 ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1361 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO_OFFER,
1362 ipmi::Privilege::Operator, mdr2DataInfoOffer);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001363
1364 // <Send MDRII Data Info>
1365 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1366 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO,
1367 NULL, cmd_mdr2_send_data_info, PRIVILEGE_OPERATOR);
1368
1369 // <Get MDRII Data Block Command>
1370 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1371 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_BLOCK,
1372 NULL, cmd_mdr2_get_data_block, PRIVILEGE_OPERATOR);
1373
1374 // <Send MDRII Data Block>
1375 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1376 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_BLOCK,
1377 NULL, cmd_mdr2_send_data_block, PRIVILEGE_OPERATOR);
1378
1379 // <Lock MDRII Data Command>
1380 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1381 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_LOCK_DATA, NULL,
1382 cmd_mdr2_lock_data, PRIVILEGE_OPERATOR);
1383
1384 // <Unlock MDRII Data Command>
1385 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1386 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_UNLOCK_DATA,
1387 NULL, cmd_mdr2_unlock_data, PRIVILEGE_OPERATOR);
1388
1389 // <Send MDRII Data Start>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001390 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1391 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_START,
1392 ipmi::Privilege::Operator, cmd_mdr2_data_start);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001393
1394 // <Send MDRII Data Done>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001395 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1396 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_DONE,
1397 ipmi::Privilege::Operator, cmd_mdr2_data_done);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001398}