blob: 2d1c92ca556d0aa695f25c15372927d15eb1495f [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;
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +000037static constexpr const uint8_t ccOemInvalidChecksum = 0x85;
Vernon Mauerya3702c12019-05-22 13:20:59 -070038
Vernon Mauerya3702c12019-05-22 13:20:59 -070039static void register_netfn_smbiosmdrv2_functions() __attribute__((constructor));
Vernon Mauerya3702c12019-05-22 13:20:59 -070040
41int MDRV2::agentLookup(const uint16_t &agentId)
42{
43 int agentIndex = -1;
44
45 if (lastAgentId == agentId)
46 {
47 return lastAgentIndex;
48 }
49
50 if (agentId == smbiosAgentId)
51 {
52 return firstAgentIndex;
53 }
54
55 return agentIndex;
56}
57
58int MDRV2::sdplusMdrv2GetProperty(const std::string &name,
59 sdbusplus::message::variant<uint8_t> &value,
60 const std::string &service)
61{
Vernon Mauery15419dd2019-05-24 09:40:30 -070062 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
Vernon Mauerya3702c12019-05-22 13:20:59 -070063 sdbusplus::message::message method =
Vernon Mauery15419dd2019-05-24 09:40:30 -070064 bus->new_method_call(service.c_str(), mdrv2Path, dbusProperties, "Get");
Vernon Mauerya3702c12019-05-22 13:20:59 -070065 method.append(mdrv2Interface, name);
66
Vernon Mauery15419dd2019-05-24 09:40:30 -070067 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -070068
69 try
70 {
Vernon Mauery15419dd2019-05-24 09:40:30 -070071 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -070072 reply.read(value);
73 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -070074 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -070075 {
76 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -070077 "Error get property, sdbusplus call failed",
78 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -070079 return -1;
80 }
81
82 return 0;
83}
84
85int MDRV2::syncDirCommonData(uint8_t idIndex, uint32_t size,
86 const std::string &service)
87{
88 std::vector<uint32_t> commonData;
Vernon Mauery15419dd2019-05-24 09:40:30 -070089 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
Vernon Mauerya3702c12019-05-22 13:20:59 -070090 sdbusplus::message::message method =
Vernon Mauery15419dd2019-05-24 09:40:30 -070091 bus->new_method_call(service.c_str(), mdrv2Path, mdrv2Interface,
92 "SynchronizeDirectoryCommonData");
Vernon Mauerya3702c12019-05-22 13:20:59 -070093 method.append(idIndex, size);
94
95 try
96 {
Vernon Mauery15419dd2019-05-24 09:40:30 -070097 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -070098 reply.read(commonData);
99 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700100 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700101 {
102 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700103 "Error sync dir common data with service",
104 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -0700105 return -1;
106 }
107
108 if (commonData.size() < syncDirCommonSize)
109 {
110 phosphor::logging::log<phosphor::logging::level::ERR>(
111 "Error sync dir common data - data length invalid");
112 return -1;
113 }
114 smbiosDir.dir[idIndex].common.dataSetSize = commonData.at(0);
115 smbiosDir.dir[idIndex].common.dataVersion = commonData.at(1);
116 smbiosDir.dir[idIndex].common.timestamp = commonData.at(2);
117
118 return 0;
119}
120
121int MDRV2::findDataId(const uint8_t *dataInfo, const size_t &len,
122 const std::string &service)
123{
124 int idIndex = -1;
125
126 if (dataInfo == nullptr)
127 {
128 phosphor::logging::log<phosphor::logging::level::ERR>(
129 "Error dataInfo, input is null point");
130 return -1;
131 }
132
Vernon Mauery15419dd2019-05-24 09:40:30 -0700133 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
134 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700135 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 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700143 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700144 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
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000271/** @brief implements mdr2 get directory command
272 * @param agentId
273 * @param dirIndex
274 * @returns IPMI completion code plus response data
275 * - dataOut
276 */
277ipmi::RspType<std::vector<uint8_t>> mdr2GetDir(uint16_t agentId,
278 uint8_t dirIndex)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700279{
Vernon Mauery15419dd2019-05-24 09:40:30 -0700280 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
281 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700282
283 if (mdrv2 == nullptr)
284 {
285 mdrv2 = std::make_unique<MDRV2>();
286 }
287
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000288 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700289 if (agentIndex == -1)
290 {
291 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000292 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
293 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700294 }
295
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000296 std::variant<uint8_t> value = 0;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700297 if (0 != mdrv2->sdplusMdrv2GetProperty("DirectoryEntries", value, service))
298 {
299 phosphor::logging::log<phosphor::logging::level::ERR>(
300 "Error getting DirEnries");
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000301 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700302 }
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000303 if (dirIndex > std::get<uint8_t>(value))
Vernon Mauerya3702c12019-05-22 13:20:59 -0700304 {
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000305 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700306 }
307
Vernon Mauery15419dd2019-05-24 09:40:30 -0700308 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700309 service.c_str(), mdrv2Path, mdrv2Interface, "GetDirectoryInformation");
310
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000311 method.append(dirIndex);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700312
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000313 std::vector<uint8_t> dataOut;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700314 try
315 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700316 sdbusplus::message::message reply = bus->call(method);
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000317 reply.read(dataOut);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700318 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700319 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700320 {
321 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700322 "Error get dir", phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700323 phosphor::logging::entry("SERVICE=%s", service.c_str()),
324 phosphor::logging::entry("PATH=%s", mdrv2Path));
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000325 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700326 }
327
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000328 constexpr size_t getDirRespSize = 6;
329 if (dataOut.size() < getDirRespSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700330 {
331 phosphor::logging::log<phosphor::logging::level::ERR>(
332 "Error get dir, response length invalid");
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000333 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700334 }
335
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000336 if (dataOut.size() > MAX_IPMI_BUFFER) // length + completion code should no
337 // more than MAX_IPMI_BUFFER
Vernon Mauerya3702c12019-05-22 13:20:59 -0700338 {
339 phosphor::logging::log<phosphor::logging::level::ERR>(
340 "Data length send from service is invalid");
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000341 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700342 }
343
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +0000344 return ipmi::responseSuccess(dataOut);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700345}
346
347ipmi_ret_t cmd_mdr2_send_dir(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
348 ipmi_request_t request, ipmi_response_t response,
349 ipmi_data_len_t data_len, ipmi_context_t context)
350{
351 auto requestData = reinterpret_cast<const MDRiiSendDirRequest *>(request);
352 std::vector<uint8_t> idVector;
353 bool teminate = false;
354
355 if (*data_len != sizeof(MDRiiSendDirRequest))
356 {
357 *data_len = 0;
358 return IPMI_CC_REQ_DATA_LEN_INVALID;
359 }
360
361 *data_len = 0;
362
Vernon Mauery15419dd2019-05-24 09:40:30 -0700363 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
364 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700365
366 if (mdrv2 == nullptr)
367 {
368 mdrv2 = std::make_unique<MDRV2>();
369 }
370
371 int agentIndex = mdrv2->agentLookup(requestData->agentId);
372 if (agentIndex == -1)
373 {
374 phosphor::logging::log<phosphor::logging::level::ERR>(
375 "Unknown agent id",
376 phosphor::logging::entry("ID=%x", requestData->agentId));
377 return IPMI_CC_PARM_OUT_OF_RANGE;
378 }
379
380 if ((requestData->dirIndex + requestData->returnedEntries) > maxDirEntries)
381 {
382 phosphor::logging::log<phosphor::logging::level::ERR>(
383 "Too many directory entries");
384 return IPMI_CC_STORGE_LEAK;
385 }
386
Vernon Mauery15419dd2019-05-24 09:40:30 -0700387 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700388 service.c_str(), mdrv2Path, mdrv2Interface, "SendDirectoryInformation");
389 method.append(requestData->dirVersion, requestData->dirIndex,
390 requestData->returnedEntries, requestData->remainingEntries);
391 uint8_t *reqPoint;
392 for (int index = 0; index < requestData->returnedEntries; index++)
393 {
394 reqPoint = (uint8_t *)&(requestData->data[index]);
395 std::copy(reqPoint, sizeof(Mdr2DirEntry) + reqPoint, idVector.data());
396 }
397 method.append(idVector);
398
399 try
400 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700401 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700402 reply.read(teminate);
403 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700404 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700405 {
406 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700407 "Error send dir", phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700408 phosphor::logging::entry("SERVICE=%s", service.c_str()),
409 phosphor::logging::entry("PATH=%s", mdrv2Path));
410 return IPMI_CC_RESPONSE_ERROR;
411 }
412
413 *data_len = 1;
414 if (teminate == false)
415 *(static_cast<uint8_t *>(response)) = 0;
416 else
417 *(static_cast<uint8_t *>(response)) = 1;
418 return IPMI_CC_OK;
419}
420
421ipmi_ret_t cmd_mdr2_get_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
422 ipmi_request_t request,
423 ipmi_response_t response,
424 ipmi_data_len_t data_len,
425 ipmi_context_t context)
426{
427 auto requestData =
428 reinterpret_cast<const MDRiiGetDataInfoRequest *>(request);
429 auto dataOut = reinterpret_cast<uint8_t *>(response);
430 std::vector<uint8_t> res;
431
432 if (*data_len < sizeof(MDRiiGetDataInfoRequest))
433 {
434 *data_len = 0;
435 return IPMI_CC_REQ_DATA_LEN_INVALID;
436 }
437
438 *data_len = 0;
439
Vernon Mauery15419dd2019-05-24 09:40:30 -0700440 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
441 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700442
443 if (mdrv2 == nullptr)
444 {
445 mdrv2 = std::make_unique<MDRV2>();
446 }
447
448 int agentIndex = mdrv2->agentLookup(requestData->agentId);
449 if (agentIndex == -1)
450 {
451 phosphor::logging::log<phosphor::logging::level::ERR>(
452 "Unknown agent id",
453 phosphor::logging::entry("ID=%x", requestData->agentId));
454 return IPMI_CC_PARM_OUT_OF_RANGE;
455 }
456
457 int idIndex =
458 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
459 sizeof(requestData->dataSetInfo.dataInfo), service);
460
461 if ((idIndex < 0) || (idIndex >= maxDirEntries))
462 {
463 phosphor::logging::log<phosphor::logging::level::ERR>(
464 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
465 return IPMI_CC_PARM_OUT_OF_RANGE;
466 }
467
Vernon Mauery15419dd2019-05-24 09:40:30 -0700468 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700469 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataInformation");
470
471 method.append(idIndex);
472
473 try
474 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700475 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700476 reply.read(res);
477 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700478 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700479 {
480 phosphor::logging::log<phosphor::logging::level::ERR>(
481 "Error get data info",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700482 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700483 phosphor::logging::entry("SERVICE=%s", service.c_str()),
484 phosphor::logging::entry("PATH=%s", mdrv2Path));
485 return IPMI_CC_RESPONSE_ERROR;
486 }
487
488 if (res.size() != sizeof(MDRiiGetDataInfoResponse))
489 {
490 phosphor::logging::log<phosphor::logging::level::ERR>(
491 "Get data info response length not invalid");
492 return IPMI_CC_UNSPECIFIED_ERROR;
493 }
494 *data_len = static_cast<size_t>(res.size());
495 std::copy(&res[0], &res[*data_len], dataOut);
496
497 return IPMI_CC_OK;
498}
499
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000500/** @brief implements mdr2 data info offer command
501 * @param agentId - Offer a agent ID to get the "Data Set ID"
502 *
503 * @returns IPMI completion code plus response data
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000504 * - dataOut - data Set Id
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000505 */
506ipmi::RspType<std::vector<uint8_t>> mdr2DataInfoOffer(uint16_t agentId)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700507{
Vernon Mauery15419dd2019-05-24 09:40:30 -0700508 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
509 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700510
511 if (mdrv2 == nullptr)
512 {
513 mdrv2 = std::make_unique<MDRV2>();
514 }
515
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000516 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700517 if (agentIndex == -1)
518 {
519 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000520 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
521 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700522 }
523
Vernon Mauery15419dd2019-05-24 09:40:30 -0700524 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700525 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataOffer");
526
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000527 std::vector<uint8_t> dataOut;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700528 try
529 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700530 sdbusplus::message::message reply = bus->call(method);
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000531 reply.read(dataOut);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700532 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700533 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700534 {
535 phosphor::logging::log<phosphor::logging::level::ERR>(
536 "Error send data info offer",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700537 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700538 phosphor::logging::entry("SERVICE=%s", service.c_str()),
539 phosphor::logging::entry("PATH=%s", mdrv2Path));
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000540 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700541 }
542
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000543 constexpr size_t respInfoSize = 16;
544 if (dataOut.size() != respInfoSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700545 {
546 phosphor::logging::log<phosphor::logging::level::ERR>(
547 "Error send data info offer, return length invalid");
jayaprakash Mutyala853d8292019-05-31 18:17:42 +0000548 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700549 }
550
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000551 return ipmi::responseSuccess(dataOut);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700552}
553
554ipmi_ret_t cmd_mdr2_send_data_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
555 ipmi_request_t request,
556 ipmi_response_t response,
557 ipmi_data_len_t data_len,
558 ipmi_context_t context)
559{
560 auto requestData =
561 reinterpret_cast<const MDRiiSendDataInfoRequest *>(request);
562 bool entryChanged = true;
563
564 if (*data_len != sizeof(MDRiiSendDataInfoRequest))
565 {
566 *data_len = 0;
567 return IPMI_CC_REQ_DATA_LEN_INVALID;
568 }
569
570 *data_len = 0;
571
572 if (requestData->dataLength > smbiosTableStorageSize)
573 {
574 phosphor::logging::log<phosphor::logging::level::ERR>(
575 "Requested data length is out of SMBIOS Table storage size.");
576 return IPMI_CC_PARM_OUT_OF_RANGE;
577 }
578
Vernon Mauery15419dd2019-05-24 09:40:30 -0700579 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
580 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700581
582 if (mdrv2 == nullptr)
583 {
584 mdrv2 = std::make_unique<MDRV2>();
585 }
586
587 int agentIndex = mdrv2->agentLookup(requestData->agentId);
588 if (agentIndex == -1)
589 {
590 phosphor::logging::log<phosphor::logging::level::ERR>(
591 "Unknown agent id",
592 phosphor::logging::entry("ID=%x", requestData->agentId));
593 return IPMI_CC_PARM_OUT_OF_RANGE;
594 }
595
596 int idIndex =
597 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
598 sizeof(requestData->dataSetInfo.dataInfo), service);
599
600 if ((idIndex < 0) || (idIndex >= maxDirEntries))
601 {
602 phosphor::logging::log<phosphor::logging::level::ERR>(
603 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
604 return IPMI_CC_PARM_OUT_OF_RANGE;
605 }
606
Vernon Mauery15419dd2019-05-24 09:40:30 -0700607 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -0700608 service.c_str(), mdrv2Path, mdrv2Interface, "SendDataInformation");
609
610 method.append((uint8_t)idIndex, requestData->validFlag,
611 requestData->dataLength, requestData->dataVersion,
612 requestData->timeStamp);
613
614 try
615 {
Vernon Mauery15419dd2019-05-24 09:40:30 -0700616 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700617 reply.read(entryChanged);
618 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700619 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700620 {
621 phosphor::logging::log<phosphor::logging::level::ERR>(
622 "Error send data info",
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700623 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -0700624 phosphor::logging::entry("SERVICE=%s", service.c_str()),
625 phosphor::logging::entry("PATH=%s", mdrv2Path));
626 return IPMI_CC_RESPONSE_ERROR;
627 }
628
629 *data_len = 1;
630
631 if (entryChanged)
632 {
633 *(static_cast<uint8_t *>(response)) = 1;
634 }
635 else
636 {
637 *(static_cast<uint8_t *>(response)) = 0;
638 }
639
640 return IPMI_CC_OK;
641}
642
643ipmi_ret_t cmd_mdr2_get_data_block(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
644 ipmi_request_t request,
645 ipmi_response_t response,
646 ipmi_data_len_t data_len,
647 ipmi_context_t context)
648{
649 auto requestData =
650 reinterpret_cast<const MDRiiGetDataBlockRequest *>(request);
651 auto responseData = reinterpret_cast<MDRiiGetDataBlockResponse *>(response);
652 std::tuple<uint8_t, uint32_t, uint32_t, std::vector<uint8_t>> res;
653 std::vector<uint8_t> resData;
654 uint8_t status = 1;
655
656 if (*data_len != sizeof(MDRiiGetDataBlockRequest))
657 {
658 *data_len = 0;
659 return IPMI_CC_REQ_DATA_LEN_INVALID;
660 }
661
662 *data_len = 0;
663
Vernon Mauerya3702c12019-05-22 13:20:59 -0700664 if (mdrv2 == nullptr)
665 {
666 mdrv2 = std::make_unique<MDRV2>();
667 }
668
669 int agentIndex = mdrv2->agentLookup(requestData->agentId);
670 if (agentIndex == -1)
671 {
672 phosphor::logging::log<phosphor::logging::level::ERR>(
673 "Unknown agent id",
674 phosphor::logging::entry("ID=%x", requestData->agentId));
675 return IPMI_CC_PARM_OUT_OF_RANGE;
676 }
677
678 int idIndex = mdrv2->findLockHandle(requestData->lockHandle);
679
680 if ((idIndex < 0) || (idIndex >= maxDirEntries))
681 {
682 phosphor::logging::log<phosphor::logging::level::ERR>(
683 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
684 return IPMI_CC_PARM_OUT_OF_RANGE;
685 }
686
687 if (requestData->xferOffset >= mdrv2->smbiosDir.dir[idIndex].common.size)
688 {
689 phosphor::logging::log<phosphor::logging::level::ERR>(
690 "Offset is outside of range.");
691 return IPMI_CC_PARM_OUT_OF_RANGE;
692 }
693
694 size_t outSize =
695 (requestData->xferLength > mdrv2->smbiosDir.dir[idIndex].xferSize)
696 ? mdrv2->smbiosDir.dir[idIndex].xferSize
697 : requestData->xferLength;
698 if (outSize > UINT_MAX - requestData->xferOffset)
699 {
700 phosphor::logging::log<phosphor::logging::level::ERR>(
701 "Out size and offset are out of range");
702 return IPMI_CC_PARM_OUT_OF_RANGE;
703 }
704 if ((requestData->xferOffset + outSize) >
705 mdrv2->smbiosDir.dir[idIndex].common.size)
706 {
707 outSize =
708 mdrv2->smbiosDir.dir[idIndex].common.size - requestData->xferOffset;
709 }
710
711 responseData->xferLength = outSize;
712 if (responseData->xferLength > requestData->xferLength)
713 {
714 phosphor::logging::log<phosphor::logging::level::ERR>(
715 "Get data block unexpected error.");
716 return IPMI_CC_UNSPECIFIED_ERROR;
717 }
718
719 if ((requestData->xferOffset + outSize) >
720 UINT_MAX -
721 reinterpret_cast<size_t>(mdrv2->smbiosDir.dir[idIndex].dataStorage))
722 {
723 phosphor::logging::log<phosphor::logging::level::ERR>(
724 "Input data to calculate checksum is out of range");
725 return IPMI_CC_PARM_OUT_OF_RANGE;
726 }
727
728 uint32_t u32Checksum = mdrv2->calcChecksum32(
729 mdrv2->smbiosDir.dir[idIndex].dataStorage + requestData->xferOffset,
730 outSize);
731 if (u32Checksum == invalidChecksum)
732 {
733 phosphor::logging::log<phosphor::logging::level::ERR>(
734 "Get data block failed - invalid checksum");
735 return IPMI_CC_OEM_INVALID_CHECKSUM;
736 }
737 responseData->checksum = u32Checksum;
738
739 *data_len = sizeof(responseData->xferLength) +
740 sizeof(responseData->checksum) + outSize;
741
742 if (*data_len > MAX_IPMI_BUFFER) // length + completion code should no more
743 // than MAX_IPMI_BUFFER
744 {
745 phosphor::logging::log<phosphor::logging::level::ERR>(
746 "Data length send from service is invalid");
747 *data_len = 0;
748 return IPMI_CC_RESPONSE_ERROR;
749 }
750
751 std::copy(
752 &mdrv2->smbiosDir.dir[idIndex].dataStorage[requestData->xferOffset],
753 &mdrv2->smbiosDir.dir[idIndex]
754 .dataStorage[requestData->xferOffset + outSize],
755 responseData->data);
756
757 return IPMI_CC_OK;
758}
759
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000760/** @brief implements mdr2 send data block command
761 * @param agentId
762 * @param lockHandle
763 * @param xferOffset
764 * @param xferLength
765 * @param checksum
766 *
767 * @returns IPMI completion code
768 */
769ipmi::RspType<> mdr2SendDataBlock(uint16_t agentId, uint16_t lockHandle,
770 uint32_t xferOffset, uint32_t xferLength,
771 uint32_t checksum)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700772{
Vernon Mauerya3702c12019-05-22 13:20:59 -0700773 if (mdrv2 == nullptr)
774 {
775 mdrv2 = std::make_unique<MDRV2>();
776 }
777
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000778 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700779 if (agentIndex == -1)
780 {
781 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000782 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
783 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700784 }
785
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000786 int idIndex = mdrv2->findLockHandle(lockHandle);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700787
788 if ((idIndex < 0) || (idIndex >= maxDirEntries))
789 {
790 phosphor::logging::log<phosphor::logging::level::ERR>(
791 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000792 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700793 }
794
795 if (mdrv2->smbiosIsUpdating(idIndex))
796 {
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000797 if (xferOffset > UINT_MAX - xferLength)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700798 {
799 phosphor::logging::log<phosphor::logging::level::ERR>(
800 "Offset and length are out of range");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000801 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700802 }
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000803 if (((xferOffset + xferLength) >
Vernon Mauerya3702c12019-05-22 13:20:59 -0700804 mdrv2->smbiosDir.dir[idIndex].maxDataSize) ||
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000805 ((xferOffset + xferLength) >
Vernon Mauerya3702c12019-05-22 13:20:59 -0700806 mdrv2->smbiosDir.dir[idIndex].common.dataSetSize))
807 {
808 phosphor::logging::log<phosphor::logging::level::ERR>(
809 "Send data block Invalid offset/length");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000810 return ipmi::responseReqDataLenExceeded();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700811 }
812 if (reinterpret_cast<size_t>(
813 mdrv2->smbiosDir.dir[idIndex].dataStorage) >
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000814 UINT_MAX - xferOffset)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700815 {
816 phosphor::logging::log<phosphor::logging::level::ERR>(
817 "Offset is out of range");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000818 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700819 }
820 uint8_t *destAddr =
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000821 mdrv2->smbiosDir.dir[idIndex].dataStorage + xferOffset;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700822 uint8_t *sourceAddr = reinterpret_cast<uint8_t *>(mdrv2->area->vPtr);
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000823 uint32_t calcChecksum = mdrv2->calcChecksum32(sourceAddr, xferLength);
824 if (calcChecksum != checksum)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700825 {
826 phosphor::logging::log<phosphor::logging::level::ERR>(
827 "Send data block Invalid checksum");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000828 return ipmi::response(ccOemInvalidChecksum);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700829 }
830 else
831 {
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000832 if (reinterpret_cast<size_t>(sourceAddr) > UINT_MAX - xferLength)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700833 {
834 phosphor::logging::log<phosphor::logging::level::ERR>(
835 "Length is out of range");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000836 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700837 }
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000838 std::copy(sourceAddr, sourceAddr + xferLength, destAddr);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700839 }
840 }
841 else
842 {
843 phosphor::logging::log<phosphor::logging::level::ERR>(
844 "Send data block failed, other data is updating");
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000845 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700846 }
847
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +0000848 return ipmi::responseSuccess();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700849}
850
851bool MDRV2::storeDatatoFlash(MDRSMBIOSHeader *mdrHdr, uint8_t *data)
852{
853 std::ofstream smbiosFile(mdrType2File,
854 std::ios_base::binary | std::ios_base::trunc);
855 if (!smbiosFile.good())
856 {
857 phosphor::logging::log<phosphor::logging::level::ERR>(
858 "Write data from flash error - Open MDRV2 table file failure");
859 return false;
860 }
861
862 try
863 {
864 smbiosFile.write(reinterpret_cast<char *>(mdrHdr),
865 sizeof(MDRSMBIOSHeader));
866 smbiosFile.write(reinterpret_cast<char *>(data), mdrHdr->dataSize);
867 }
868 catch (std::ofstream::failure &e)
869 {
870 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -0700871 "Write data from flash error - write data error",
872 phosphor::logging::entry("ERROR=%s", e.what()));
Vernon Mauerya3702c12019-05-22 13:20:59 -0700873 return false;
874 }
875
876 return true;
877}
878
879void SharedMemoryArea::Initialize(uint32_t addr, uint32_t areaSize)
880{
881 int memDriver = 0;
882
883 // open mem driver for the system memory access
884 memDriver = open("/dev/vgasharedmem", O_RDONLY);
885 if (memDriver < 0)
886 {
887 phosphor::logging::log<phosphor::logging::level::ERR>(
888 "Cannot access mem driver");
889 throw std::system_error(EIO, std::generic_category());
890 }
891
892 // map the system memory
893 vPtr = mmap(NULL, // where to map to: don't mind
894 areaSize, // how many bytes ?
895 PROT_READ, // want to read and write
896 MAP_SHARED, // no copy on write
897 memDriver, // handle to /dev/mem
898 (physicalAddr & pageMask)); // hopefully the Text-buffer :-)
899
900 close(memDriver);
901 if (vPtr == MAP_FAILED)
902 {
903 phosphor::logging::log<phosphor::logging::level::ERR>(
904 "Failed to map share memory");
905 throw std::system_error(EIO, std::generic_category());
906 }
907 size = areaSize;
908 physicalAddr = addr;
909}
910
911bool MDRV2::smbiosUnlock(uint8_t index)
912{
913 bool ret;
914 switch (smbiosDir.dir[index].stage)
915 {
916 case MDR2SMBIOSStatusEnum::mdr2Updating:
917 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updated;
918 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
919
920 timer->stop();
921 smbiosDir.dir[index].lockHandle = 0;
922 ret = true;
923 break;
924
925 case MDR2SMBIOSStatusEnum::mdr2Updated:
926 case MDR2SMBIOSStatusEnum::mdr2Loaded:
927 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
928
929 timer->stop();
930
931 smbiosDir.dir[index].lockHandle = 0;
932 ret = true;
933 break;
934
935 default:
936 break;
937 }
938
939 return ret;
940}
941
942bool MDRV2::smbiosTryLock(uint8_t flag, uint8_t index, uint16_t *session,
943 uint16_t timeout)
944{
945 bool ret = false;
946 uint32_t u32Status = 0;
947
948 if (timeout == 0)
949 {
950 timeout = defaultTimeout;
951 }
952 std::chrono::microseconds usec(timeout * sysClock);
953
954 switch (smbiosDir.dir[index].stage)
955 {
956 case MDR2SMBIOSStatusEnum::mdr2Updating:
957 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
958 {
959 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
960 timer->start(usec);
961 lockIndex = index;
962
963 *session = getSessionHandle(&smbiosDir);
964 smbiosDir.dir[index].lockHandle = *session;
965 ret = true;
966 }
967 break;
968 case MDR2SMBIOSStatusEnum::mdr2Init:
969 if (flag)
970 {
971 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updating;
972 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
973 timer->start(usec);
974 lockIndex = index;
975
976 *session = getSessionHandle(&smbiosDir);
977 smbiosDir.dir[index].lockHandle = *session;
978 ret = true;
979 }
980 break;
981
982 case MDR2SMBIOSStatusEnum::mdr2Updated:
983 case MDR2SMBIOSStatusEnum::mdr2Loaded:
984 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock)
985 {
986 if (flag)
987 {
988 smbiosDir.dir[index].stage =
989 MDR2SMBIOSStatusEnum::mdr2Updating;
990 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock;
991 }
992 else
993 {
994 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock;
995 }
996
997 timer->start(usec);
998 lockIndex = index;
999
1000 *session = getSessionHandle(&smbiosDir);
1001 smbiosDir.dir[index].lockHandle = *session;
1002 ret = true;
1003 }
1004 break;
1005
1006 default:
1007 break;
1008 }
1009 return ret;
1010}
1011
1012void MDRV2::timeoutHandler()
1013{
1014 smbiosUnlock(lockIndex);
1015 mdrv2->area.reset(nullptr);
1016}
1017
1018ipmi_ret_t cmd_mdr2_lock_data(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1019 ipmi_request_t request, ipmi_response_t response,
1020 ipmi_data_len_t data_len, ipmi_context_t context)
1021{
1022 auto requestData = reinterpret_cast<const MDRiiLockDataRequest *>(request);
1023 auto responseData = reinterpret_cast<MDRiiLockDataResponse *>(response);
1024 uint16_t session = 0;
1025
1026 std::tuple<bool, uint8_t, uint16_t, uint32_t, uint32_t, uint32_t> res;
1027
1028 if (*data_len < sizeof(MDRiiLockDataRequest))
1029 {
1030 *data_len = 0;
1031 return IPMI_CC_REQ_DATA_LEN_INVALID;
1032 }
1033
1034 *data_len = 0;
1035
1036 if (mdrv2 == nullptr)
1037 {
1038 mdrv2 = std::make_unique<MDRV2>();
1039 }
1040
1041 int agentIndex = mdrv2->agentLookup(requestData->agentId);
1042 if (agentIndex == -1)
1043 {
1044 phosphor::logging::log<phosphor::logging::level::ERR>(
1045 "Unknown agent id",
1046 phosphor::logging::entry("ID=%x", requestData->agentId));
1047 return IPMI_CC_PARM_OUT_OF_RANGE;
1048 }
1049
Vernon Mauery15419dd2019-05-24 09:40:30 -07001050 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1051 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001052
1053 int idIndex =
1054 mdrv2->findDataId(requestData->dataSetInfo.dataInfo,
1055 sizeof(requestData->dataSetInfo.dataInfo), service);
1056
1057 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1058 {
1059 phosphor::logging::log<phosphor::logging::level::ERR>(
1060 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
1061 return IPMI_CC_PARM_OUT_OF_RANGE;
1062 }
1063
1064 if (!mdrv2->smbiosTryLock(0, idIndex, &session, requestData->timeout))
1065 {
1066 phosphor::logging::log<phosphor::logging::level::ERR>(
1067 "Lock Data failed - cannot lock idIndex");
1068 return IPMI_CC_PARAMETER_NOT_SUPPORT_IN_PRESENT_STATE;
1069 }
1070
1071 *data_len = sizeof(MDRiiLockDataResponse);
1072
1073 responseData->mdrVersion = mdr2Version;
1074 responseData->lockHandle = session;
1075 responseData->dataLength = mdrv2->smbiosDir.dir[idIndex].common.size;
1076 responseData->xferAddress = mdrv2->smbiosDir.dir[idIndex].xferBuff;
1077 responseData->xferLength = mdrv2->smbiosDir.dir[idIndex].xferSize;
1078
1079 return IPMI_CC_OK;
1080}
1081
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001082/** @brief implements mdr2 unlock data command
1083 * @param agentId
1084 * @param lockHandle
1085 *
1086 * @returns IPMI completion code
1087 */
1088ipmi::RspType<> mdr2UnlockData(uint16_t agentId, uint16_t lockHandle)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001089{
1090 phosphor::logging::log<phosphor::logging::level::ERR>("unlock data");
Vernon Mauerya3702c12019-05-22 13:20:59 -07001091
Vernon Mauerya3702c12019-05-22 13:20:59 -07001092 if (mdrv2 == nullptr)
1093 {
1094 mdrv2 = std::make_unique<MDRV2>();
1095 }
1096
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001097 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001098 if (agentIndex == -1)
1099 {
1100 phosphor::logging::log<phosphor::logging::level::ERR>(
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001101 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1102 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001103 }
1104
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001105 int idIndex = mdrv2->findLockHandle(lockHandle);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001106
1107 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1108 {
1109 phosphor::logging::log<phosphor::logging::level::ERR>(
1110 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001111 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001112 }
1113
1114 if (!mdrv2->smbiosUnlock(idIndex))
1115 {
1116 phosphor::logging::log<phosphor::logging::level::ERR>(
1117 "Unlock Data failed - cannot unlock idIndex");
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001118 return ipmi::responseCommandNotAvailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001119 }
1120
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001121 return ipmi::responseSuccess();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001122}
1123
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001124/**
1125@brief This command is executed after POST BIOS to get the session info.
1126
1127@param - agentId, dataInfo, dataLength, xferAddress, xferLength, timeout.
1128
1129@return xferStartAck and session on success.
1130**/
1131ipmi::RspType<uint8_t, uint16_t>
1132 cmd_mdr2_data_start(uint16_t agentId, std::array<uint8_t, 16> dataInfo,
1133 uint32_t dataLength, uint32_t xferAddress,
1134 uint32_t xferLength, uint16_t timeout)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001135{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001136 uint16_t session = 0;
1137
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001138 if (dataLength > smbiosTableStorageSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001139 {
1140 phosphor::logging::log<phosphor::logging::level::ERR>(
1141 "Requested data length is out of SMBIOS Table storage size.");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001142 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001143 }
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001144 if ((xferLength + xferAddress) > mdriiSMSize)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001145 {
1146 phosphor::logging::log<phosphor::logging::level::ERR>(
1147 "Invalid data address and size");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001148 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001149 }
1150
Vernon Mauery15419dd2019-05-24 09:40:30 -07001151 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1152 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001153
1154 if (mdrv2 == nullptr)
1155 {
1156 mdrv2 = std::make_unique<MDRV2>();
1157 }
1158
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001159 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001160 if (agentIndex == -1)
1161 {
1162 phosphor::logging::log<phosphor::logging::level::ERR>(
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001163 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1164 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001165 }
1166
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001167 int idIndex = mdrv2->findDataId(dataInfo.data(), sizeof(dataInfo), service);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001168
1169 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1170 {
1171 phosphor::logging::log<phosphor::logging::level::ERR>(
1172 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001173 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001174 }
1175
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001176 if (mdrv2->smbiosTryLock(1, idIndex, &session, timeout))
Vernon Mauerya3702c12019-05-22 13:20:59 -07001177 {
1178 try
1179 {
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001180 mdrv2->area =
1181 std::make_unique<SharedMemoryArea>(xferAddress, xferLength);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001182 }
1183 catch (const std::system_error &e)
1184 {
1185 mdrv2->smbiosUnlock(idIndex);
1186 phosphor::logging::log<phosphor::logging::level::ERR>(
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001187 "Unable to access share memory",
1188 phosphor::logging::entry("ERROR=%s", e.what()));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001189 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001190 }
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001191 mdrv2->smbiosDir.dir[idIndex].common.size = dataLength;
Vernon Mauerya3702c12019-05-22 13:20:59 -07001192 mdrv2->smbiosDir.dir[idIndex].lockHandle = session;
1193 if (-1 ==
1194 mdrv2->syncDirCommonData(
1195 idIndex, mdrv2->smbiosDir.dir[idIndex].common.size, service))
1196 {
1197 phosphor::logging::log<phosphor::logging::level::ERR>(
1198 "Unable to sync data to service");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001199 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001200 }
1201 }
1202 else
1203 {
1204 phosphor::logging::log<phosphor::logging::level::ERR>(
1205 "Canot lock smbios");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001206 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001207 }
1208
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001209 static constexpr uint8_t xferStartAck = 1;
Vernon Mauerya3702c12019-05-22 13:20:59 -07001210
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001211 return ipmi::responseSuccess(xferStartAck, session);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001212}
1213
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001214/**
1215@brief This command is executed to close the session.
1216
1217@param - agentId, lockHandle.
1218
1219@return completion code on success.
1220**/
1221ipmi::RspType<> cmd_mdr2_data_done(uint16_t agentId, uint16_t lockHandle)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001222{
Vernon Mauerya3702c12019-05-22 13:20:59 -07001223
1224 if (mdrv2 == nullptr)
1225 {
1226 mdrv2 = std::make_unique<MDRV2>();
1227 }
1228
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001229 int agentIndex = mdrv2->agentLookup(agentId);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001230 if (agentIndex == -1)
1231 {
1232 phosphor::logging::log<phosphor::logging::level::ERR>(
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001233 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId));
1234 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001235 }
1236
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001237 int idIndex = mdrv2->findLockHandle(lockHandle);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001238
1239 if ((idIndex < 0) || (idIndex >= maxDirEntries))
1240 {
1241 phosphor::logging::log<phosphor::logging::level::ERR>(
1242 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001243 return ipmi::responseParmOutOfRange();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001244 }
1245
1246 if (!mdrv2->smbiosUnlock(idIndex))
1247 {
1248 phosphor::logging::log<phosphor::logging::level::ERR>(
1249 "Send data done failed - cannot unlock idIndex");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001250 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001251 }
1252
1253 mdrv2->area.reset(nullptr);
1254 MDRSMBIOSHeader mdr2Smbios;
1255 mdr2Smbios.mdrType = mdrTypeII;
1256 mdr2Smbios.dirVer = mdrv2->smbiosDir.dir[0].common.dataVersion;
1257 mdr2Smbios.timestamp = mdrv2->smbiosDir.dir[0].common.timestamp;
1258 mdr2Smbios.dataSize = mdrv2->smbiosDir.dir[0].common.size;
1259
1260 if (access(smbiosPath, 0) == -1)
1261 {
1262 int flag = mkdir(smbiosPath, S_IRWXU);
1263 if (flag != 0)
1264 {
1265 phosphor::logging::log<phosphor::logging::level::ERR>(
1266 "create folder failed for writting smbios file");
1267 }
1268 }
1269 if (!mdrv2->storeDatatoFlash(
1270 &mdr2Smbios, mdrv2->smbiosDir.dir[smbiosDirIndex].dataStorage))
1271 {
1272 phosphor::logging::log<phosphor::logging::level::ERR>(
1273 "MDR2 Store data to flash failed");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001274 return ipmi::responseDestinationUnavailable();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001275 }
Vernon Mauerya3702c12019-05-22 13:20:59 -07001276 bool status = false;
Vernon Mauery15419dd2019-05-24 09:40:30 -07001277 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1278 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path);
1279 sdbusplus::message::message method = bus->new_method_call(
Vernon Mauerya3702c12019-05-22 13:20:59 -07001280 service.c_str(), mdrv2Path, mdrv2Interface, "AgentSynchronizeData");
1281
1282 try
1283 {
Vernon Mauery15419dd2019-05-24 09:40:30 -07001284 sdbusplus::message::message reply = bus->call(method);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001285 reply.read(status);
1286 }
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001287 catch (sdbusplus::exception_t &e)
Vernon Mauerya3702c12019-05-22 13:20:59 -07001288 {
1289 phosphor::logging::log<phosphor::logging::level::ERR>(
1290 "Error Sync data with service",
Vernon Maueryc7d517e2019-06-18 14:27:00 -07001291 phosphor::logging::entry("ERROR=%s", e.what()),
Vernon Mauerya3702c12019-05-22 13:20:59 -07001292 phosphor::logging::entry("SERVICE=%s", service.c_str()),
1293 phosphor::logging::entry("PATH=%s", mdrv2Path));
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001294 return ipmi::responseResponseError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001295 }
1296
1297 if (!status)
1298 {
1299 phosphor::logging::log<phosphor::logging::level::ERR>(
1300 "Sync data with service failure");
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001301 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001302 }
1303
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001304 return ipmi::responseSuccess();
Vernon Mauerya3702c12019-05-22 13:20:59 -07001305}
1306
1307static void register_netfn_smbiosmdrv2_functions(void)
1308{
1309 // MDR V2 Command
1310 // <Get MDRII Status Command>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001311 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1312 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_AGENT_STATUS,
1313 ipmi::Privilege::Operator, mdr2AgentStatus);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001314
1315 // <Get MDRII Directory Command>
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001316 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1317 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DIR,
1318 ipmi::Privilege::Operator, mdr2GetDir);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001319
1320 // <Send MDRII Directory Command>
1321 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1322 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DIR, NULL,
1323 cmd_mdr2_send_dir, PRIVILEGE_OPERATOR);
1324
1325 // <Get MDRII Data Info Command>
1326 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1327 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_INFO,
1328 NULL, cmd_mdr2_get_data_info, PRIVILEGE_OPERATOR);
1329
1330 // <Send MDRII Info Offer>
jayaprakash Mutyala853d8292019-05-31 18:17:42 +00001331 ipmi::registerHandler(
1332 ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1333 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO_OFFER,
1334 ipmi::Privilege::Operator, mdr2DataInfoOffer);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001335
1336 // <Send MDRII Data Info>
1337 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1338 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_INFO,
1339 NULL, cmd_mdr2_send_data_info, PRIVILEGE_OPERATOR);
1340
1341 // <Get MDRII Data Block Command>
1342 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1343 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_GET_DATA_BLOCK,
1344 NULL, cmd_mdr2_get_data_block, PRIVILEGE_OPERATOR);
1345
1346 // <Send MDRII Data Block>
jayaprakash Mutyala3104b3f2019-06-10 19:23:07 +00001347 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1348 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_SEND_DATA_BLOCK,
1349 ipmi::Privilege::Operator, mdr2SendDataBlock);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001350
1351 // <Lock MDRII Data Command>
1352 ipmi_register_callback(NETFUN_INTEL_APP_OEM,
1353 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_LOCK_DATA, NULL,
1354 cmd_mdr2_lock_data, PRIVILEGE_OPERATOR);
1355
1356 // <Unlock MDRII Data Command>
jayaprakash Mutyaladad548b2019-06-12 15:29:39 +00001357 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1358 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_UNLOCK_DATA,
1359 ipmi::Privilege::Operator, mdr2UnlockData);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001360
1361 // <Send MDRII Data Start>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001362 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1363 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_START,
1364 ipmi::Privilege::Operator, cmd_mdr2_data_start);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001365
1366 // <Send MDRII Data Done>
Deepak Kumar Sahu529d4152019-05-31 18:23:14 +00001367 ipmi::registerHandler(ipmi::prioOemBase, NETFUN_INTEL_APP_OEM,
1368 IPMI_NETFN_INTEL_OEM_APP_CMD::MDRII_DATA_DONE,
1369 ipmi::Privilege::Operator, cmd_mdr2_data_done);
Vernon Mauerya3702c12019-05-22 13:20:59 -07001370}