blob: 39890b396feb453aa80777616f76952d74a3c62e [file] [log] [blame]
Cheng C Yangeecaf822019-12-19 00:34:23 +08001/*
Zhikui Ren18a5ab92020-09-01 21:35:20 -07002// Copyright (c) 2018 Intel Corporation
Cheng C Yangeecaf822019-12-19 00:34:23 +08003//
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 "mdrv2.hpp"
18
Jie Yang08e4a6d2021-08-23 13:07:41 -070019#include "pcieslot.hpp"
20
Cheng C Yangeecaf822019-12-19 00:34:23 +080021#include <sys/mman.h>
22
Cheng C Yangeecaf822019-12-19 00:34:23 +080023#include <phosphor-logging/elog-errors.hpp>
24#include <sdbusplus/exception.hpp>
25#include <xyz/openbmc_project/Smbios/MDR_V2/error.hpp>
26
Zhikui Ren18a5ab92020-09-01 21:35:20 -070027#include <fstream>
28
Cheng C Yangeecaf822019-12-19 00:34:23 +080029namespace phosphor
30{
31namespace smbios
32{
33
34std::vector<uint8_t> MDR_V2::getDirectoryInformation(uint8_t dirIndex)
35{
Cheng C Yang608e52d2019-12-19 00:39:50 +080036 std::vector<uint8_t> responseDir;
37 if (dirIndex > smbiosDir.dirEntries)
38 {
39 responseDir.push_back(0);
Kuiying Wanga4c08702020-11-18 19:27:20 +080040 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
41 InvalidParameter();
Cheng C Yang608e52d2019-12-19 00:39:50 +080042 }
43 responseDir.push_back(mdr2Version);
44 responseDir.push_back(smbiosDir.dirVersion);
45 uint8_t returnedEntries = smbiosDir.dirEntries - dirIndex;
46 responseDir.push_back(returnedEntries);
47 if ((dirIndex + returnedEntries) >= smbiosDir.dirEntries)
48 {
49 responseDir.push_back(0);
50 }
51 else
52 {
53 responseDir.push_back(smbiosDir.dirEntries - dirIndex -
54 returnedEntries);
55 }
56 for (uint8_t index = dirIndex; index < smbiosDir.dirEntries; index++)
57 {
58 for (uint8_t indexId = 0; indexId < sizeof(DataIdStruct); indexId++)
59 {
60 responseDir.push_back(
61 smbiosDir.dir[index].common.id.dataInfo[indexId]);
62 }
63 }
64
65 return responseDir;
Cheng C Yangeecaf822019-12-19 00:34:23 +080066}
67
68bool MDR_V2::smbiosIsAvailForUpdate(uint8_t index)
69{
70 bool ret = false;
Chen Yugangad0e7652020-12-01 14:49:54 +080071 if (index >= maxDirEntries)
Cheng C Yangeecaf822019-12-19 00:34:23 +080072 {
73 return ret;
74 }
75
76 switch (smbiosDir.dir[index].stage)
77 {
78 case MDR2SMBIOSStatusEnum::mdr2Updating:
79 ret = false;
80 break;
81
82 case MDR2SMBIOSStatusEnum::mdr2Init:
83 // This *looks* like there should be a break statement here,
84 // as the effects of the previous statement are a noop given
85 // the following code that this falls through to.
86 // We've elected not to change it, though, since it's been
87 // this way since the old generation, and it would affect
88 // the way the code functions.
89 // If it ain't broke, don't fix it.
90
91 case MDR2SMBIOSStatusEnum::mdr2Loaded:
92 case MDR2SMBIOSStatusEnum::mdr2Updated:
93 if (smbiosDir.dir[index].lock == MDR2DirLockEnum::mdr2DirLock)
94 {
95 ret = false;
96 }
97 else
98 {
99 ret = true;
100 }
101 break;
102
103 default:
104 break;
105 }
106
107 return ret;
108}
109
110std::vector<uint8_t> MDR_V2::getDataOffer()
111{
112 std::vector<uint8_t> offer(sizeof(DataIdStruct));
113 if (smbiosIsAvailForUpdate(0))
114 {
115 std::copy(smbiosDir.dir[0].common.id.dataInfo,
116 &smbiosDir.dir[0].common.id.dataInfo[16], offer.data());
117 }
118 else
119 {
120 phosphor::logging::log<phosphor::logging::level::ERR>(
121 "smbios is not ready for update");
Kuiying Wanga4c08702020-11-18 19:27:20 +0800122 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
123 UpdateInProgress();
Cheng C Yangeecaf822019-12-19 00:34:23 +0800124 }
125 return offer;
126}
127
128inline uint8_t MDR_V2::smbiosValidFlag(uint8_t index)
129{
130 FlagStatus ret = FlagStatus::flagIsInvalid;
131 MDR2SMBIOSStatusEnum stage = smbiosDir.dir[index].stage;
132 MDR2DirLockEnum lock = smbiosDir.dir[index].lock;
133
134 switch (stage)
135 {
136 case MDR2SMBIOSStatusEnum::mdr2Loaded:
137 case MDR2SMBIOSStatusEnum::mdr2Updated:
138 if (lock == MDR2DirLockEnum::mdr2DirLock)
139 {
140 ret = FlagStatus::flagIsLocked; // locked
141 }
142 else
143 {
144 ret = FlagStatus::flagIsValid; // valid
145 }
146 break;
147
148 case MDR2SMBIOSStatusEnum::mdr2Updating:
149 case MDR2SMBIOSStatusEnum::mdr2Init:
150 ret = FlagStatus::flagIsInvalid; // invalid
151 break;
152
153 default:
154 break;
155 }
156
157 return static_cast<uint8_t>(ret);
158}
159
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700160// If source variable size is 4 bytes (uint32_t) and destination is Vector type
161// is 1 byte (uint8_t), then by using this API can copy data byte by byte. For
162// Example copying data from smbiosDir.dir[idIndex].common.size and
163// smbiosDir.dir[idIndex].common.timestamp to vector variable responseInfo
164template <typename T>
165void appendReversed(std::vector<uint8_t>& vector, const T& value)
166{
167 auto data = reinterpret_cast<const uint8_t*>(&value);
168 std::reverse_copy(data, data + sizeof(value), std::back_inserter(vector));
169}
170
Cheng C Yangeecaf822019-12-19 00:34:23 +0800171std::vector<uint8_t> MDR_V2::getDataInformation(uint8_t idIndex)
172{
173 std::vector<uint8_t> responseInfo;
174 responseInfo.push_back(mdr2Version);
175
176 if (idIndex >= maxDirEntries)
177 {
Kuiying Wanga4c08702020-11-18 19:27:20 +0800178 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
179 InvalidParameter();
Cheng C Yangeecaf822019-12-19 00:34:23 +0800180 }
181
182 for (uint8_t index = 0; index < sizeof(DataIdStruct); index++)
183 {
184 responseInfo.push_back(
185 smbiosDir.dir[idIndex].common.id.dataInfo[index]);
186 }
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700187
Cheng C Yangeecaf822019-12-19 00:34:23 +0800188 responseInfo.push_back(smbiosValidFlag(idIndex));
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700189 appendReversed(responseInfo, smbiosDir.dir[idIndex].common.size);
Cheng C Yangeecaf822019-12-19 00:34:23 +0800190 responseInfo.push_back(smbiosDir.dir[idIndex].common.dataVersion);
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700191 appendReversed(responseInfo, smbiosDir.dir[idIndex].common.timestamp);
Cheng C Yangeecaf822019-12-19 00:34:23 +0800192
193 return responseInfo;
194}
195
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700196bool MDR_V2::readDataFromFlash(MDRSMBIOSHeader* mdrHdr, uint8_t* data)
197{
198 if (mdrHdr == nullptr)
199 {
200 phosphor::logging::log<phosphor::logging::level::ERR>(
201 "Read data from flash error - Invalid mdr header");
202 return false;
203 }
204 if (data == nullptr)
205 {
206 phosphor::logging::log<phosphor::logging::level::ERR>(
207 "Read data from flash error - Invalid data point");
208 return false;
209 }
210 std::ifstream smbiosFile(mdrType2File, std::ios_base::binary);
211 if (!smbiosFile.good())
212 {
213 phosphor::logging::log<phosphor::logging::level::ERR>(
214 "Read data from flash error - Open MDRV2 table file failure");
215 return false;
216 }
217 smbiosFile.clear();
218 smbiosFile.seekg(0, std::ios_base::end);
219 int fileLength = smbiosFile.tellg();
220 smbiosFile.seekg(0, std::ios_base::beg);
221 if (fileLength < sizeof(MDRSMBIOSHeader))
222 {
223 phosphor::logging::log<phosphor::logging::level::ERR>(
224 "MDR V2 file size is smaller than mdr header");
225 return false;
226 }
227 smbiosFile.read(reinterpret_cast<char*>(mdrHdr), sizeof(MDRSMBIOSHeader));
228 if (mdrHdr->dataSize > smbiosTableStorageSize)
229 {
230 phosphor::logging::log<phosphor::logging::level::ERR>(
231 "Data size out of limitation");
232 smbiosFile.close();
233 return false;
234 }
235 fileLength -= sizeof(MDRSMBIOSHeader);
236 if (fileLength < mdrHdr->dataSize)
237 {
238 smbiosFile.read(reinterpret_cast<char*>(data), fileLength);
239 }
240 else
241 {
242 smbiosFile.read(reinterpret_cast<char*>(data), mdrHdr->dataSize);
243 }
244 smbiosFile.close();
245 return true;
246}
247
Cheng C Yangeecaf822019-12-19 00:34:23 +0800248bool MDR_V2::sendDirectoryInformation(uint8_t dirVersion, uint8_t dirIndex,
249 uint8_t returnedEntries,
250 uint8_t remainingEntries,
251 std::vector<uint8_t> dirEntry)
252{
Cheng C Yang608e52d2019-12-19 00:39:50 +0800253 bool teminate = false;
254 if ((dirIndex >= maxDirEntries) || (returnedEntries < 1))
255 {
256 phosphor::logging::log<phosphor::logging::level::ERR>(
257 "Send Dir info failed - input parameter invalid");
Kuiying Wanga4c08702020-11-18 19:27:20 +0800258 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
259 InvalidParameter();
Cheng C Yang608e52d2019-12-19 00:39:50 +0800260 }
Mansi Joshiecbd71b2021-08-10 22:14:08 +0530261 if ((static_cast<size_t>(returnedEntries) * sizeof(DataIdStruct)) !=
262 dirEntry.size())
Cheng C Yang608e52d2019-12-19 00:39:50 +0800263 {
264 phosphor::logging::log<phosphor::logging::level::ERR>(
265 "Directory size invalid");
Kuiying Wanga4c08702020-11-18 19:27:20 +0800266 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
267 InvalidParameter();
Cheng C Yang608e52d2019-12-19 00:39:50 +0800268 }
269 if (dirVersion == smbiosDir.dirVersion)
270 {
271 teminate = true;
272 }
273 else
274 {
275 if (remainingEntries > 0)
276 {
277 teminate = false;
278 }
279 else
280 {
281 teminate = true;
282 smbiosDir.dirVersion = dirVersion;
283 }
284 uint8_t idIndex = dirIndex;
Mansi Joshiecbd71b2021-08-10 22:14:08 +0530285 smbiosDir.dirEntries = returnedEntries;
Cheng C Yang608e52d2019-12-19 00:39:50 +0800286
287 uint8_t* pData = dirEntry.data();
288 if (pData == nullptr)
289 {
290 return false;
291 }
292 for (uint8_t index = 0; index < returnedEntries; index++)
293 {
Mansi Joshiecbd71b2021-08-10 22:14:08 +0530294 auto data = reinterpret_cast<const DataIdStruct*>(pData);
295 std::copy(data->dataInfo, data->dataInfo + sizeof(DataIdStruct),
Cheng C Yang608e52d2019-12-19 00:39:50 +0800296 smbiosDir.dir[idIndex + index].common.id.dataInfo);
Mansi Joshiecbd71b2021-08-10 22:14:08 +0530297 pData += sizeof(DataIdStruct);
Cheng C Yang608e52d2019-12-19 00:39:50 +0800298 }
299 }
300 return teminate;
Cheng C Yangeecaf822019-12-19 00:34:23 +0800301}
302
303bool MDR_V2::sendDataInformation(uint8_t idIndex, uint8_t flag,
304 uint32_t dataLen, uint32_t dataVer,
305 uint32_t timeStamp)
306{
307 if (idIndex >= maxDirEntries)
308 {
Kuiying Wanga4c08702020-11-18 19:27:20 +0800309 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
310 InvalidParameter();
Cheng C Yangeecaf822019-12-19 00:34:23 +0800311 }
312 int entryChanged = 0;
313 if (smbiosDir.dir[idIndex].common.dataSetSize != dataLen)
314 {
315 entryChanged++;
316 smbiosDir.dir[idIndex].common.dataSetSize = dataLen;
317 }
318
319 if (smbiosDir.dir[idIndex].common.dataVersion != dataVer)
320 {
321 entryChanged++;
322 smbiosDir.dir[idIndex].common.dataVersion = dataVer;
323 }
324
325 if (smbiosDir.dir[idIndex].common.timestamp != timeStamp)
326 {
327 entryChanged++;
328 smbiosDir.dir[idIndex].common.timestamp = timeStamp;
329 }
330 if (entryChanged == 0)
331 {
332 return false;
333 }
334 return true;
335}
336
337int MDR_V2::findIdIndex(std::vector<uint8_t> dataInfo)
338{
339 if (dataInfo.size() != sizeof(DataIdStruct))
340 {
341 phosphor::logging::log<phosphor::logging::level::ERR>(
342 "Length of dataInfo invalid");
Kuiying Wanga4c08702020-11-18 19:27:20 +0800343 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
344 InvalidId();
Cheng C Yangeecaf822019-12-19 00:34:23 +0800345 }
346 std::array<uint8_t, 16> arrayDataInfo;
347
348 std::copy(dataInfo.begin(), dataInfo.end(), arrayDataInfo.begin());
349
350 for (int index = 0; index < smbiosDir.dirEntries; index++)
351 {
352 int info = 0;
353 for (; info < arrayDataInfo.size(); info++)
354 {
355 if (arrayDataInfo[info] !=
356 smbiosDir.dir[index].common.id.dataInfo[info])
357 {
358 break;
359 }
360 }
361 if (info == arrayDataInfo.size())
362 {
363 return index;
364 }
365 }
Kuiying Wanga4c08702020-11-18 19:27:20 +0800366 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::InvalidId();
Cheng C Yangeecaf822019-12-19 00:34:23 +0800367}
368
369uint8_t MDR_V2::directoryEntries(uint8_t value)
370{
371 value = smbiosDir.dirEntries;
372 return sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V2::
373 directoryEntries(value);
374}
375
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800376void MDR_V2::systemInfoUpdate()
377{
378 cpus.clear();
379
380 int num = getTotalCpuSlot();
381 if (num == -1)
382 {
383 phosphor::logging::log<phosphor::logging::level::ERR>(
384 "get cpu total slot failed");
385 return;
386 }
387
388 for (int index = 0; index < num; index++)
389 {
390 std::string path = cpuPath + std::to_string(index);
391 cpus.emplace_back(std::make_unique<phosphor::smbios::Cpu>(
392 bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage));
393 }
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800394
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700395#ifdef DIMM_DBUS
396
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800397 dimms.clear();
398
399 num = getTotalDimmSlot();
400 if (num == -1)
401 {
402 phosphor::logging::log<phosphor::logging::level::ERR>(
403 "get dimm total slot failed");
404 return;
405 }
406
407 for (int index = 0; index < num; index++)
408 {
409 std::string path = dimmPath + std::to_string(index);
410 dimms.emplace_back(std::make_unique<phosphor::smbios::Dimm>(
411 bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage));
412 }
Cheng C Yangb4651b92019-12-19 00:59:01 +0800413
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700414#endif
415
Jie Yang08e4a6d2021-08-23 13:07:41 -0700416 pcies.clear();
417 num = getTotalPcieSlot();
418 if (num == -1)
419 {
420 phosphor::logging::log<phosphor::logging::level::ERR>(
421 "get pcie total slot failed");
422 return;
423 }
424
425 for (int index = 0; index < num; index++)
426 {
427 std::string path = pciePath + std::to_string(index);
428 pcies.emplace_back(std::make_unique<phosphor::smbios::Pcie>(
429 bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage));
430 }
431
Cheng C Yangb4651b92019-12-19 00:59:01 +0800432 system.reset();
433 system = std::make_unique<System>(
434 bus, systemPath, smbiosDir.dir[smbiosDirIndex].dataStorage);
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800435}
436
437int MDR_V2::getTotalCpuSlot()
438{
439 uint8_t* dataIn = smbiosDir.dir[smbiosDirIndex].dataStorage;
440 int num = 0;
441
442 if (dataIn == nullptr)
443 {
444 phosphor::logging::log<phosphor::logging::level::ERR>(
445 "get cpu total slot failed - no storage data");
446 return -1;
447 }
448
449 while (1)
450 {
451 dataIn = getSMBIOSTypePtr(dataIn, processorsType);
452 if (dataIn == nullptr)
453 {
454 break;
455 }
456 num++;
457 dataIn = smbiosNextPtr(dataIn);
458 if (dataIn == nullptr)
459 {
460 break;
461 }
462 if (num >= limitEntryLen)
463 {
464 break;
465 }
466 }
467
468 return num;
469}
470
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800471int MDR_V2::getTotalDimmSlot()
472{
473 uint8_t* dataIn = smbiosDir.dir[smbiosDirIndex].dataStorage;
474 uint8_t num = 0;
475
476 if (dataIn == nullptr)
477 {
478 phosphor::logging::log<phosphor::logging::level::ERR>(
479 "Fail to get dimm total slot - no storage data");
480 return -1;
481 }
482
483 while (1)
484 {
485 dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);
486 if (dataIn == nullptr)
487 {
488 break;
489 }
490 num++;
491 dataIn = smbiosNextPtr(dataIn);
492 if (dataIn == nullptr)
493 {
494 break;
495 }
496 if (num >= limitEntryLen)
497 {
498 break;
499 }
500 }
501
502 return num;
503}
504
Jie Yang08e4a6d2021-08-23 13:07:41 -0700505int MDR_V2::getTotalPcieSlot()
506{
507 uint8_t* dataIn = smbiosDir.dir[smbiosDirIndex].dataStorage;
508 int num = 0;
509
510 if (dataIn == nullptr)
511 {
512 phosphor::logging::log<phosphor::logging::level::ERR>(
513 "Fail to get total system slot - no storage data");
514 return -1;
515 }
516
517 while (1)
518 {
519 dataIn = getSMBIOSTypePtr(dataIn, systemSlots);
520 if (dataIn == nullptr)
521 {
522 break;
523 }
524
525 /* System slot type offset. Check if the slot is a PCIE slots. All
526 * PCIE slot type are hardcoded in a table.
527 */
528 if (pcieSmbiosType.find(*(dataIn + 5)) != pcieSmbiosType.end())
529 {
530 num++;
531 }
532 dataIn = smbiosNextPtr(dataIn);
533 if (dataIn == nullptr)
534 {
535 break;
536 }
537 if (num >= limitEntryLen)
538 {
539 break;
540 }
541 }
542
543 return num;
544}
545
Cheng C Yangeecaf822019-12-19 00:34:23 +0800546bool MDR_V2::agentSynchronizeData()
547{
Cheng C Yangec634252019-12-19 00:42:36 +0800548 struct MDRSMBIOSHeader mdr2SMBIOS;
549 bool status = readDataFromFlash(&mdr2SMBIOS,
550 smbiosDir.dir[smbiosDirIndex].dataStorage);
551 if (!status)
552 {
553 phosphor::logging::log<phosphor::logging::level::ERR>(
554 "agent data sync failed - read data from flash failed");
555 return false;
556 }
557 else
558 {
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800559 systemInfoUpdate();
Cheng C Yangec634252019-12-19 00:42:36 +0800560 smbiosDir.dir[smbiosDirIndex].common.dataVersion = mdr2SMBIOS.dirVer;
561 smbiosDir.dir[smbiosDirIndex].common.timestamp = mdr2SMBIOS.timestamp;
562 smbiosDir.dir[smbiosDirIndex].common.size = mdr2SMBIOS.dataSize;
563 smbiosDir.dir[smbiosDirIndex].stage = MDR2SMBIOSStatusEnum::mdr2Loaded;
564 smbiosDir.dir[smbiosDirIndex].lock = MDR2DirLockEnum::mdr2DirUnlock;
565 }
Cheng C Yangec634252019-12-19 00:42:36 +0800566 return true;
Cheng C Yangeecaf822019-12-19 00:34:23 +0800567}
568
569std::vector<uint32_t> MDR_V2::synchronizeDirectoryCommonData(uint8_t idIndex,
570 uint32_t size)
571{
Cheng C Yangec634252019-12-19 00:42:36 +0800572 std::chrono::microseconds usec(
573 defaultTimeout); // default lock time out is 2s
574 std::vector<uint32_t> result;
575 smbiosDir.dir[idIndex].common.size = size;
576 result.push_back(smbiosDir.dir[idIndex].common.dataSetSize);
577 result.push_back(smbiosDir.dir[idIndex].common.dataVersion);
578 result.push_back(smbiosDir.dir[idIndex].common.timestamp);
579
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700580 timer.expires_after(usec);
581 timer.async_wait([this](boost::system::error_code ec) {
582 if (ec || this == nullptr)
583 {
584 phosphor::logging::log<phosphor::logging::level::ERR>(
585 "Timer Error!");
586 return;
587 }
588 agentSynchronizeData();
589 });
Cheng C Yangec634252019-12-19 00:42:36 +0800590 return result;
Cheng C Yangeecaf822019-12-19 00:34:23 +0800591}
592
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700593std::vector<boost::container::flat_map<std::string, RecordVariant>>
594 MDR_V2::getRecordType(size_t type)
595{
596
597 std::vector<boost::container::flat_map<std::string, RecordVariant>> ret;
598 if (type == memoryDeviceType)
599 {
600
601 uint8_t* dataIn = smbiosDir.dir[smbiosDirIndex].dataStorage;
602
603 if (dataIn == nullptr)
604 {
Kuiying Wanga4c08702020-11-18 19:27:20 +0800605 throw std::runtime_error("Data not populated");
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700606 }
607
608 do
609 {
610 dataIn =
611 getSMBIOSTypePtr(dataIn, memoryDeviceType, sizeof(MemoryInfo));
612 if (dataIn == nullptr)
613 {
614 break;
615 }
616 boost::container::flat_map<std::string, RecordVariant>& record =
617 ret.emplace_back();
618
619 auto memoryInfo = reinterpret_cast<MemoryInfo*>(dataIn);
620
621 record["Type"] = memoryInfo->type;
622 record["Length"] = memoryInfo->length;
623 record["Handle"] = uint16_t(memoryInfo->handle);
624 record["Physical Memory Array Handle"] =
625 uint16_t(memoryInfo->phyArrayHandle);
626 record["Memory Error Information Handle"] =
627 uint16_t(memoryInfo->errInfoHandle);
628 record["Total Width"] = uint16_t(memoryInfo->totalWidth);
629 record["Data Width"] = uint16_t(memoryInfo->dataWidth);
630 record["Size"] = uint16_t(memoryInfo->size);
631 record["Form Factor"] = memoryInfo->formFactor;
632 record["Device Set"] = memoryInfo->deviceSet;
633 record["Device Locator"] = positionToString(
634 memoryInfo->deviceLocator, memoryInfo->length, dataIn);
635 record["Bank Locator"] = positionToString(
636 memoryInfo->bankLocator, memoryInfo->length, dataIn);
637 record["Memory Type"] = memoryInfo->memoryType;
638 record["Type Detail"] = uint16_t(memoryInfo->typeDetail);
639 record["Speed"] = uint16_t(memoryInfo->speed);
640 record["Manufacturer"] = positionToString(
641 memoryInfo->manufacturer, memoryInfo->length, dataIn);
642 record["Serial Number"] = positionToString(
643 memoryInfo->serialNum, memoryInfo->length, dataIn);
644 record["Asset Tag"] = positionToString(memoryInfo->assetTag,
645 memoryInfo->length, dataIn);
646 record["Part Number"] = positionToString(
647 memoryInfo->partNum, memoryInfo->length, dataIn);
648 record["Attributes"] = memoryInfo->attributes;
649 record["Extended Size"] = uint32_t(memoryInfo->extendedSize);
650 record["Configured Memory Speed"] =
651 uint32_t(memoryInfo->confClockSpeed);
652 record["Minimum voltage"] = uint16_t(memoryInfo->minimumVoltage);
653 record["Maximum voltage"] = uint16_t(memoryInfo->maximumVoltage);
654 record["Configured voltage"] =
655 uint16_t(memoryInfo->configuredVoltage);
656 record["Memory Technology"] = memoryInfo->memoryTechnology;
657 record["Memory Operating Mode Capabilty"] =
658 uint16_t(memoryInfo->memoryOperatingModeCap);
659 record["Firmare Version"] = memoryInfo->firwareVersion;
660 record["Module Manufacturer ID"] =
661 uint16_t(memoryInfo->modelManufId);
662 record["Module Product ID"] = uint16_t(memoryInfo->modelProdId);
663 record["Memory Subsystem Controller Manufacturer ID"] =
664 uint16_t(memoryInfo->memSubConManufId);
665 record["Memory Subsystem Controller Product Id"] =
666 uint16_t(memoryInfo->memSubConProdId);
667 record["Non-volatile Size"] = uint64_t(memoryInfo->nvSize);
668 record["Volatile Size"] = uint64_t(memoryInfo->volatileSize);
669 record["Cache Size"] = uint64_t(memoryInfo->cacheSize);
670 record["Logical Size"] = uint64_t(memoryInfo->logicalSize);
671 } while ((dataIn = smbiosNextPtr(dataIn)) != nullptr);
672
673 return ret;
674 }
675
Kuiying Wanga4c08702020-11-18 19:27:20 +0800676 throw std::invalid_argument("Invalid record type");
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700677 return ret;
678}
679
Cheng C Yangeecaf822019-12-19 00:34:23 +0800680} // namespace smbios
681} // namespace phosphor