blob: 1d173c411764eefec5003b55e273b2137c21328f [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
19#include <sys/mman.h>
20
Cheng C Yangeecaf822019-12-19 00:34:23 +080021#include <phosphor-logging/elog-errors.hpp>
22#include <sdbusplus/exception.hpp>
23#include <xyz/openbmc_project/Smbios/MDR_V2/error.hpp>
24
Zhikui Ren18a5ab92020-09-01 21:35:20 -070025#include <fstream>
26
Cheng C Yangeecaf822019-12-19 00:34:23 +080027namespace phosphor
28{
29namespace smbios
30{
31
32std::vector<uint8_t> MDR_V2::getDirectoryInformation(uint8_t dirIndex)
33{
Cheng C Yang608e52d2019-12-19 00:39:50 +080034 std::vector<uint8_t> responseDir;
35 if (dirIndex > smbiosDir.dirEntries)
36 {
37 responseDir.push_back(0);
Kuiying Wanga4c08702020-11-18 19:27:20 +080038 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
39 InvalidParameter();
Cheng C Yang608e52d2019-12-19 00:39:50 +080040 }
41 responseDir.push_back(mdr2Version);
42 responseDir.push_back(smbiosDir.dirVersion);
43 uint8_t returnedEntries = smbiosDir.dirEntries - dirIndex;
44 responseDir.push_back(returnedEntries);
45 if ((dirIndex + returnedEntries) >= smbiosDir.dirEntries)
46 {
47 responseDir.push_back(0);
48 }
49 else
50 {
51 responseDir.push_back(smbiosDir.dirEntries - dirIndex -
52 returnedEntries);
53 }
54 for (uint8_t index = dirIndex; index < smbiosDir.dirEntries; index++)
55 {
56 for (uint8_t indexId = 0; indexId < sizeof(DataIdStruct); indexId++)
57 {
58 responseDir.push_back(
59 smbiosDir.dir[index].common.id.dataInfo[indexId]);
60 }
61 }
62
63 return responseDir;
Cheng C Yangeecaf822019-12-19 00:34:23 +080064}
65
66bool MDR_V2::smbiosIsAvailForUpdate(uint8_t index)
67{
68 bool ret = false;
Chen Yugangad0e7652020-12-01 14:49:54 +080069 if (index >= maxDirEntries)
Cheng C Yangeecaf822019-12-19 00:34:23 +080070 {
71 return ret;
72 }
73
74 switch (smbiosDir.dir[index].stage)
75 {
76 case MDR2SMBIOSStatusEnum::mdr2Updating:
77 ret = false;
78 break;
79
80 case MDR2SMBIOSStatusEnum::mdr2Init:
81 // This *looks* like there should be a break statement here,
82 // as the effects of the previous statement are a noop given
83 // the following code that this falls through to.
84 // We've elected not to change it, though, since it's been
85 // this way since the old generation, and it would affect
86 // the way the code functions.
87 // If it ain't broke, don't fix it.
88
89 case MDR2SMBIOSStatusEnum::mdr2Loaded:
90 case MDR2SMBIOSStatusEnum::mdr2Updated:
91 if (smbiosDir.dir[index].lock == MDR2DirLockEnum::mdr2DirLock)
92 {
93 ret = false;
94 }
95 else
96 {
97 ret = true;
98 }
99 break;
100
101 default:
102 break;
103 }
104
105 return ret;
106}
107
108std::vector<uint8_t> MDR_V2::getDataOffer()
109{
110 std::vector<uint8_t> offer(sizeof(DataIdStruct));
111 if (smbiosIsAvailForUpdate(0))
112 {
113 std::copy(smbiosDir.dir[0].common.id.dataInfo,
114 &smbiosDir.dir[0].common.id.dataInfo[16], offer.data());
115 }
116 else
117 {
118 phosphor::logging::log<phosphor::logging::level::ERR>(
119 "smbios is not ready for update");
Kuiying Wanga4c08702020-11-18 19:27:20 +0800120 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
121 UpdateInProgress();
Cheng C Yangeecaf822019-12-19 00:34:23 +0800122 }
123 return offer;
124}
125
126inline uint8_t MDR_V2::smbiosValidFlag(uint8_t index)
127{
128 FlagStatus ret = FlagStatus::flagIsInvalid;
129 MDR2SMBIOSStatusEnum stage = smbiosDir.dir[index].stage;
130 MDR2DirLockEnum lock = smbiosDir.dir[index].lock;
131
132 switch (stage)
133 {
134 case MDR2SMBIOSStatusEnum::mdr2Loaded:
135 case MDR2SMBIOSStatusEnum::mdr2Updated:
136 if (lock == MDR2DirLockEnum::mdr2DirLock)
137 {
138 ret = FlagStatus::flagIsLocked; // locked
139 }
140 else
141 {
142 ret = FlagStatus::flagIsValid; // valid
143 }
144 break;
145
146 case MDR2SMBIOSStatusEnum::mdr2Updating:
147 case MDR2SMBIOSStatusEnum::mdr2Init:
148 ret = FlagStatus::flagIsInvalid; // invalid
149 break;
150
151 default:
152 break;
153 }
154
155 return static_cast<uint8_t>(ret);
156}
157
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700158// If source variable size is 4 bytes (uint32_t) and destination is Vector type
159// is 1 byte (uint8_t), then by using this API can copy data byte by byte. For
160// Example copying data from smbiosDir.dir[idIndex].common.size and
161// smbiosDir.dir[idIndex].common.timestamp to vector variable responseInfo
162template <typename T>
163void appendReversed(std::vector<uint8_t>& vector, const T& value)
164{
165 auto data = reinterpret_cast<const uint8_t*>(&value);
166 std::reverse_copy(data, data + sizeof(value), std::back_inserter(vector));
167}
168
Cheng C Yangeecaf822019-12-19 00:34:23 +0800169std::vector<uint8_t> MDR_V2::getDataInformation(uint8_t idIndex)
170{
171 std::vector<uint8_t> responseInfo;
172 responseInfo.push_back(mdr2Version);
173
174 if (idIndex >= maxDirEntries)
175 {
Kuiying Wanga4c08702020-11-18 19:27:20 +0800176 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
177 InvalidParameter();
Cheng C Yangeecaf822019-12-19 00:34:23 +0800178 }
179
180 for (uint8_t index = 0; index < sizeof(DataIdStruct); index++)
181 {
182 responseInfo.push_back(
183 smbiosDir.dir[idIndex].common.id.dataInfo[index]);
184 }
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700185
Cheng C Yangeecaf822019-12-19 00:34:23 +0800186 responseInfo.push_back(smbiosValidFlag(idIndex));
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700187 appendReversed(responseInfo, smbiosDir.dir[idIndex].common.size);
Cheng C Yangeecaf822019-12-19 00:34:23 +0800188 responseInfo.push_back(smbiosDir.dir[idIndex].common.dataVersion);
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700189 appendReversed(responseInfo, smbiosDir.dir[idIndex].common.timestamp);
Cheng C Yangeecaf822019-12-19 00:34:23 +0800190
191 return responseInfo;
192}
193
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700194bool MDR_V2::readDataFromFlash(MDRSMBIOSHeader* mdrHdr, uint8_t* data)
195{
196 if (mdrHdr == nullptr)
197 {
198 phosphor::logging::log<phosphor::logging::level::ERR>(
199 "Read data from flash error - Invalid mdr header");
200 return false;
201 }
202 if (data == nullptr)
203 {
204 phosphor::logging::log<phosphor::logging::level::ERR>(
205 "Read data from flash error - Invalid data point");
206 return false;
207 }
208 std::ifstream smbiosFile(mdrType2File, std::ios_base::binary);
209 if (!smbiosFile.good())
210 {
211 phosphor::logging::log<phosphor::logging::level::ERR>(
212 "Read data from flash error - Open MDRV2 table file failure");
213 return false;
214 }
215 smbiosFile.clear();
216 smbiosFile.seekg(0, std::ios_base::end);
217 int fileLength = smbiosFile.tellg();
218 smbiosFile.seekg(0, std::ios_base::beg);
219 if (fileLength < sizeof(MDRSMBIOSHeader))
220 {
221 phosphor::logging::log<phosphor::logging::level::ERR>(
222 "MDR V2 file size is smaller than mdr header");
223 return false;
224 }
225 smbiosFile.read(reinterpret_cast<char*>(mdrHdr), sizeof(MDRSMBIOSHeader));
226 if (mdrHdr->dataSize > smbiosTableStorageSize)
227 {
228 phosphor::logging::log<phosphor::logging::level::ERR>(
229 "Data size out of limitation");
230 smbiosFile.close();
231 return false;
232 }
233 fileLength -= sizeof(MDRSMBIOSHeader);
234 if (fileLength < mdrHdr->dataSize)
235 {
236 smbiosFile.read(reinterpret_cast<char*>(data), fileLength);
237 }
238 else
239 {
240 smbiosFile.read(reinterpret_cast<char*>(data), mdrHdr->dataSize);
241 }
242 smbiosFile.close();
243 return true;
244}
245
Cheng C Yangeecaf822019-12-19 00:34:23 +0800246bool MDR_V2::sendDirectoryInformation(uint8_t dirVersion, uint8_t dirIndex,
247 uint8_t returnedEntries,
248 uint8_t remainingEntries,
249 std::vector<uint8_t> dirEntry)
250{
Cheng C Yang608e52d2019-12-19 00:39:50 +0800251 bool teminate = false;
252 if ((dirIndex >= maxDirEntries) || (returnedEntries < 1))
253 {
254 phosphor::logging::log<phosphor::logging::level::ERR>(
255 "Send Dir info failed - input parameter invalid");
Kuiying Wanga4c08702020-11-18 19:27:20 +0800256 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
257 InvalidParameter();
Cheng C Yang608e52d2019-12-19 00:39:50 +0800258 }
Mansi Joshiecbd71b2021-08-10 22:14:08 +0530259 if ((static_cast<size_t>(returnedEntries) * sizeof(DataIdStruct)) !=
260 dirEntry.size())
Cheng C Yang608e52d2019-12-19 00:39:50 +0800261 {
262 phosphor::logging::log<phosphor::logging::level::ERR>(
263 "Directory size invalid");
Kuiying Wanga4c08702020-11-18 19:27:20 +0800264 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
265 InvalidParameter();
Cheng C Yang608e52d2019-12-19 00:39:50 +0800266 }
267 if (dirVersion == smbiosDir.dirVersion)
268 {
269 teminate = true;
270 }
271 else
272 {
273 if (remainingEntries > 0)
274 {
275 teminate = false;
276 }
277 else
278 {
279 teminate = true;
280 smbiosDir.dirVersion = dirVersion;
281 }
282 uint8_t idIndex = dirIndex;
Mansi Joshiecbd71b2021-08-10 22:14:08 +0530283 smbiosDir.dirEntries = returnedEntries;
Cheng C Yang608e52d2019-12-19 00:39:50 +0800284
285 uint8_t* pData = dirEntry.data();
286 if (pData == nullptr)
287 {
288 return false;
289 }
290 for (uint8_t index = 0; index < returnedEntries; index++)
291 {
Mansi Joshiecbd71b2021-08-10 22:14:08 +0530292 auto data = reinterpret_cast<const DataIdStruct*>(pData);
293 std::copy(data->dataInfo, data->dataInfo + sizeof(DataIdStruct),
Cheng C Yang608e52d2019-12-19 00:39:50 +0800294 smbiosDir.dir[idIndex + index].common.id.dataInfo);
Mansi Joshiecbd71b2021-08-10 22:14:08 +0530295 pData += sizeof(DataIdStruct);
Cheng C Yang608e52d2019-12-19 00:39:50 +0800296 }
297 }
298 return teminate;
Cheng C Yangeecaf822019-12-19 00:34:23 +0800299}
300
301bool MDR_V2::sendDataInformation(uint8_t idIndex, uint8_t flag,
302 uint32_t dataLen, uint32_t dataVer,
303 uint32_t timeStamp)
304{
305 if (idIndex >= maxDirEntries)
306 {
Kuiying Wanga4c08702020-11-18 19:27:20 +0800307 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
308 InvalidParameter();
Cheng C Yangeecaf822019-12-19 00:34:23 +0800309 }
310 int entryChanged = 0;
311 if (smbiosDir.dir[idIndex].common.dataSetSize != dataLen)
312 {
313 entryChanged++;
314 smbiosDir.dir[idIndex].common.dataSetSize = dataLen;
315 }
316
317 if (smbiosDir.dir[idIndex].common.dataVersion != dataVer)
318 {
319 entryChanged++;
320 smbiosDir.dir[idIndex].common.dataVersion = dataVer;
321 }
322
323 if (smbiosDir.dir[idIndex].common.timestamp != timeStamp)
324 {
325 entryChanged++;
326 smbiosDir.dir[idIndex].common.timestamp = timeStamp;
327 }
328 if (entryChanged == 0)
329 {
330 return false;
331 }
332 return true;
333}
334
335int MDR_V2::findIdIndex(std::vector<uint8_t> dataInfo)
336{
337 if (dataInfo.size() != sizeof(DataIdStruct))
338 {
339 phosphor::logging::log<phosphor::logging::level::ERR>(
340 "Length of dataInfo invalid");
Kuiying Wanga4c08702020-11-18 19:27:20 +0800341 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::
342 InvalidId();
Cheng C Yangeecaf822019-12-19 00:34:23 +0800343 }
344 std::array<uint8_t, 16> arrayDataInfo;
345
346 std::copy(dataInfo.begin(), dataInfo.end(), arrayDataInfo.begin());
347
348 for (int index = 0; index < smbiosDir.dirEntries; index++)
349 {
350 int info = 0;
351 for (; info < arrayDataInfo.size(); info++)
352 {
353 if (arrayDataInfo[info] !=
354 smbiosDir.dir[index].common.id.dataInfo[info])
355 {
356 break;
357 }
358 }
359 if (info == arrayDataInfo.size())
360 {
361 return index;
362 }
363 }
Kuiying Wanga4c08702020-11-18 19:27:20 +0800364 throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V2::Error::InvalidId();
Cheng C Yangeecaf822019-12-19 00:34:23 +0800365}
366
367uint8_t MDR_V2::directoryEntries(uint8_t value)
368{
369 value = smbiosDir.dirEntries;
370 return sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V2::
371 directoryEntries(value);
372}
373
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800374void MDR_V2::systemInfoUpdate()
375{
376 cpus.clear();
377
378 int num = getTotalCpuSlot();
379 if (num == -1)
380 {
381 phosphor::logging::log<phosphor::logging::level::ERR>(
382 "get cpu total slot failed");
383 return;
384 }
385
386 for (int index = 0; index < num; index++)
387 {
388 std::string path = cpuPath + std::to_string(index);
389 cpus.emplace_back(std::make_unique<phosphor::smbios::Cpu>(
390 bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage));
391 }
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800392
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700393#ifdef DIMM_DBUS
394
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800395 dimms.clear();
396
397 num = getTotalDimmSlot();
398 if (num == -1)
399 {
400 phosphor::logging::log<phosphor::logging::level::ERR>(
401 "get dimm total slot failed");
402 return;
403 }
404
405 for (int index = 0; index < num; index++)
406 {
407 std::string path = dimmPath + std::to_string(index);
408 dimms.emplace_back(std::make_unique<phosphor::smbios::Dimm>(
409 bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage));
410 }
Cheng C Yangb4651b92019-12-19 00:59:01 +0800411
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700412#endif
413
Cheng C Yangb4651b92019-12-19 00:59:01 +0800414 system.reset();
415 system = std::make_unique<System>(
416 bus, systemPath, smbiosDir.dir[smbiosDirIndex].dataStorage);
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800417}
418
419int MDR_V2::getTotalCpuSlot()
420{
421 uint8_t* dataIn = smbiosDir.dir[smbiosDirIndex].dataStorage;
422 int num = 0;
423
424 if (dataIn == nullptr)
425 {
426 phosphor::logging::log<phosphor::logging::level::ERR>(
427 "get cpu total slot failed - no storage data");
428 return -1;
429 }
430
431 while (1)
432 {
433 dataIn = getSMBIOSTypePtr(dataIn, processorsType);
434 if (dataIn == nullptr)
435 {
436 break;
437 }
438 num++;
439 dataIn = smbiosNextPtr(dataIn);
440 if (dataIn == nullptr)
441 {
442 break;
443 }
444 if (num >= limitEntryLen)
445 {
446 break;
447 }
448 }
449
450 return num;
451}
452
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800453int MDR_V2::getTotalDimmSlot()
454{
455 uint8_t* dataIn = smbiosDir.dir[smbiosDirIndex].dataStorage;
456 uint8_t num = 0;
457
458 if (dataIn == nullptr)
459 {
460 phosphor::logging::log<phosphor::logging::level::ERR>(
461 "Fail to get dimm total slot - no storage data");
462 return -1;
463 }
464
465 while (1)
466 {
467 dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);
468 if (dataIn == nullptr)
469 {
470 break;
471 }
472 num++;
473 dataIn = smbiosNextPtr(dataIn);
474 if (dataIn == nullptr)
475 {
476 break;
477 }
478 if (num >= limitEntryLen)
479 {
480 break;
481 }
482 }
483
484 return num;
485}
486
Cheng C Yangeecaf822019-12-19 00:34:23 +0800487bool MDR_V2::agentSynchronizeData()
488{
Cheng C Yangec634252019-12-19 00:42:36 +0800489 struct MDRSMBIOSHeader mdr2SMBIOS;
490 bool status = readDataFromFlash(&mdr2SMBIOS,
491 smbiosDir.dir[smbiosDirIndex].dataStorage);
492 if (!status)
493 {
494 phosphor::logging::log<phosphor::logging::level::ERR>(
495 "agent data sync failed - read data from flash failed");
496 return false;
497 }
498 else
499 {
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800500 systemInfoUpdate();
Cheng C Yangec634252019-12-19 00:42:36 +0800501 smbiosDir.dir[smbiosDirIndex].common.dataVersion = mdr2SMBIOS.dirVer;
502 smbiosDir.dir[smbiosDirIndex].common.timestamp = mdr2SMBIOS.timestamp;
503 smbiosDir.dir[smbiosDirIndex].common.size = mdr2SMBIOS.dataSize;
504 smbiosDir.dir[smbiosDirIndex].stage = MDR2SMBIOSStatusEnum::mdr2Loaded;
505 smbiosDir.dir[smbiosDirIndex].lock = MDR2DirLockEnum::mdr2DirUnlock;
506 }
Cheng C Yangec634252019-12-19 00:42:36 +0800507 return true;
Cheng C Yangeecaf822019-12-19 00:34:23 +0800508}
509
510std::vector<uint32_t> MDR_V2::synchronizeDirectoryCommonData(uint8_t idIndex,
511 uint32_t size)
512{
Cheng C Yangec634252019-12-19 00:42:36 +0800513 std::chrono::microseconds usec(
514 defaultTimeout); // default lock time out is 2s
515 std::vector<uint32_t> result;
516 smbiosDir.dir[idIndex].common.size = size;
517 result.push_back(smbiosDir.dir[idIndex].common.dataSetSize);
518 result.push_back(smbiosDir.dir[idIndex].common.dataVersion);
519 result.push_back(smbiosDir.dir[idIndex].common.timestamp);
520
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700521 timer.expires_after(usec);
522 timer.async_wait([this](boost::system::error_code ec) {
523 if (ec || this == nullptr)
524 {
525 phosphor::logging::log<phosphor::logging::level::ERR>(
526 "Timer Error!");
527 return;
528 }
529 agentSynchronizeData();
530 });
Cheng C Yangec634252019-12-19 00:42:36 +0800531 return result;
Cheng C Yangeecaf822019-12-19 00:34:23 +0800532}
533
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700534std::vector<boost::container::flat_map<std::string, RecordVariant>>
535 MDR_V2::getRecordType(size_t type)
536{
537
538 std::vector<boost::container::flat_map<std::string, RecordVariant>> ret;
539 if (type == memoryDeviceType)
540 {
541
542 uint8_t* dataIn = smbiosDir.dir[smbiosDirIndex].dataStorage;
543
544 if (dataIn == nullptr)
545 {
Kuiying Wanga4c08702020-11-18 19:27:20 +0800546 throw std::runtime_error("Data not populated");
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700547 }
548
549 do
550 {
551 dataIn =
552 getSMBIOSTypePtr(dataIn, memoryDeviceType, sizeof(MemoryInfo));
553 if (dataIn == nullptr)
554 {
555 break;
556 }
557 boost::container::flat_map<std::string, RecordVariant>& record =
558 ret.emplace_back();
559
560 auto memoryInfo = reinterpret_cast<MemoryInfo*>(dataIn);
561
562 record["Type"] = memoryInfo->type;
563 record["Length"] = memoryInfo->length;
564 record["Handle"] = uint16_t(memoryInfo->handle);
565 record["Physical Memory Array Handle"] =
566 uint16_t(memoryInfo->phyArrayHandle);
567 record["Memory Error Information Handle"] =
568 uint16_t(memoryInfo->errInfoHandle);
569 record["Total Width"] = uint16_t(memoryInfo->totalWidth);
570 record["Data Width"] = uint16_t(memoryInfo->dataWidth);
571 record["Size"] = uint16_t(memoryInfo->size);
572 record["Form Factor"] = memoryInfo->formFactor;
573 record["Device Set"] = memoryInfo->deviceSet;
574 record["Device Locator"] = positionToString(
575 memoryInfo->deviceLocator, memoryInfo->length, dataIn);
576 record["Bank Locator"] = positionToString(
577 memoryInfo->bankLocator, memoryInfo->length, dataIn);
578 record["Memory Type"] = memoryInfo->memoryType;
579 record["Type Detail"] = uint16_t(memoryInfo->typeDetail);
580 record["Speed"] = uint16_t(memoryInfo->speed);
581 record["Manufacturer"] = positionToString(
582 memoryInfo->manufacturer, memoryInfo->length, dataIn);
583 record["Serial Number"] = positionToString(
584 memoryInfo->serialNum, memoryInfo->length, dataIn);
585 record["Asset Tag"] = positionToString(memoryInfo->assetTag,
586 memoryInfo->length, dataIn);
587 record["Part Number"] = positionToString(
588 memoryInfo->partNum, memoryInfo->length, dataIn);
589 record["Attributes"] = memoryInfo->attributes;
590 record["Extended Size"] = uint32_t(memoryInfo->extendedSize);
591 record["Configured Memory Speed"] =
592 uint32_t(memoryInfo->confClockSpeed);
593 record["Minimum voltage"] = uint16_t(memoryInfo->minimumVoltage);
594 record["Maximum voltage"] = uint16_t(memoryInfo->maximumVoltage);
595 record["Configured voltage"] =
596 uint16_t(memoryInfo->configuredVoltage);
597 record["Memory Technology"] = memoryInfo->memoryTechnology;
598 record["Memory Operating Mode Capabilty"] =
599 uint16_t(memoryInfo->memoryOperatingModeCap);
600 record["Firmare Version"] = memoryInfo->firwareVersion;
601 record["Module Manufacturer ID"] =
602 uint16_t(memoryInfo->modelManufId);
603 record["Module Product ID"] = uint16_t(memoryInfo->modelProdId);
604 record["Memory Subsystem Controller Manufacturer ID"] =
605 uint16_t(memoryInfo->memSubConManufId);
606 record["Memory Subsystem Controller Product Id"] =
607 uint16_t(memoryInfo->memSubConProdId);
608 record["Non-volatile Size"] = uint64_t(memoryInfo->nvSize);
609 record["Volatile Size"] = uint64_t(memoryInfo->volatileSize);
610 record["Cache Size"] = uint64_t(memoryInfo->cacheSize);
611 record["Logical Size"] = uint64_t(memoryInfo->logicalSize);
612 } while ((dataIn = smbiosNextPtr(dataIn)) != nullptr);
613
614 return ret;
615 }
616
Kuiying Wanga4c08702020-11-18 19:27:20 +0800617 throw std::invalid_argument("Invalid record type");
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700618 return ret;
619}
620
Cheng C Yangeecaf822019-12-19 00:34:23 +0800621} // namespace smbios
622} // namespace phosphor