blob: a307332a403fca4479555a1a0f1b0da846d51782 [file] [log] [blame]
Cheng C Yang3e3269a2019-12-02 15:11:30 +08001/*
Zhikui Ren18a5ab92020-09-01 21:35:20 -07002// Copyright (c) 2018 Intel Corporation
Cheng C Yang3e3269a2019-12-02 15:11:30 +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#pragma once
18
Zhikui Ren18a5ab92020-09-01 21:35:20 -070019#include <phosphor-logging/elog-errors.hpp>
20
Cheng C Yang3e3269a2019-12-02 15:11:30 +080021#include <array>
22
Zhikui Ren18a5ab92020-09-01 21:35:20 -070023static constexpr const char* mdrType2File = "/var/lib/smbios/smbios2";
Cheng C Yang3e3269a2019-12-02 15:11:30 +080024static constexpr const char* smbiosPath = "/var/lib/smbios";
Zhikui Ren18a5ab92020-09-01 21:35:20 -070025
Cheng C Yangeecaf822019-12-19 00:34:23 +080026static constexpr uint16_t mdrSMBIOSSize = 32 * 1024;
Cheng C Yang3e3269a2019-12-02 15:11:30 +080027
Zhikui Ren18a5ab92020-09-01 21:35:20 -070028constexpr uint16_t smbiosAgentId = 0x0101;
29constexpr int firstAgentIndex = 1;
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +080030
Zhikui Ren18a5ab92020-09-01 21:35:20 -070031constexpr uint8_t maxDirEntries = 4;
32constexpr uint32_t mdr2SMSize = 0x00100000;
33constexpr uint32_t mdr2SMBaseAddress = 0x9FF00000;
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +080034
Zhikui Ren18a5ab92020-09-01 21:35:20 -070035constexpr uint8_t mdrTypeII = 2;
36
37constexpr uint8_t mdr2Version = 2;
38constexpr uint8_t smbiosAgentVersion = 1;
39
40constexpr uint32_t pageMask = 0xf000;
41constexpr int smbiosDirIndex = 0;
42
43constexpr uint32_t smbiosTableVersion = 15;
44constexpr uint32_t smbiosTableTimestamp = 0x45464748;
45constexpr uint32_t smbiosSMMemoryOffset = 0;
46constexpr uint32_t smbiosSMMemorySize = 1024 * 1024;
47constexpr uint32_t smbiosTableStorageSize = 64 * 1024;
48constexpr uint32_t defaultTimeout = 20000;
49
50enum class MDR2SMBIOSStatusEnum
51{
52 mdr2Init = 0,
53 mdr2Loaded = 1,
54 mdr2Updated = 2,
55 mdr2Updating = 3
56};
57
58enum class MDR2DirLockEnum
59{
60 mdr2DirUnlock = 0,
61 mdr2DirLock = 1
62};
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +080063
Cheng C Yang3e3269a2019-12-02 15:11:30 +080064enum class DirDataRequestEnum
65{
66 dirDataNotRequested = 0x00,
67 dirDataRequested = 0x01
68};
69
70enum class FlagStatus
71{
72 flagIsInvalid = 0,
73 flagIsValid = 1,
74 flagIsLocked = 2
75};
76
Zhikui Ren18a5ab92020-09-01 21:35:20 -070077typedef struct
78{
79 uint8_t dataInfo[16];
80} DataIdStruct;
81
82typedef struct
83{
84 DataIdStruct id;
85 uint32_t size;
86 uint32_t dataSetSize;
87 uint8_t dataVersion;
88 uint32_t timestamp;
89} Mdr2DirEntry;
90
91typedef struct
92{
93 Mdr2DirEntry common;
94 MDR2SMBIOSStatusEnum stage;
95 MDR2DirLockEnum lock;
96 uint16_t lockHandle;
97 uint32_t xferBuff;
98 uint32_t xferSize;
99 uint32_t maxDataSize;
100 uint8_t* dataStorage;
101} Mdr2DirLocalStruct;
102
103typedef struct
104{
105 uint8_t agentVersion;
106 uint8_t dirVersion;
107 uint8_t dirEntries;
108 uint8_t status; // valid / locked / etc
109 uint8_t remoteDirVersion;
110 uint16_t sessionHandle;
111 Mdr2DirLocalStruct dir[maxDirEntries];
112} Mdr2DirStruct;
113
114struct MDRSMBIOSHeader
115{
116 uint8_t dirVer;
117 uint8_t mdrType;
118 uint32_t timestamp;
119 uint32_t dataSize;
120} __attribute__((packed));
121
122static constexpr const char* cpuPath =
123 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu";
124
125static constexpr const char* dimmPath =
126 "/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm";
127
128static constexpr const char* systemPath =
129 "/xyz/openbmc_project/inventory/system/chassis/motherboard/bios";
130
Cheng C Yang3e3269a2019-12-02 15:11:30 +0800131typedef enum
132{
133 biosType = 0,
134 systemType = 1,
135 baseboardType = 2,
136 chassisType = 3,
137 processorsType = 4,
138 memoryControllerType = 5,
139 memoryModuleInformationType = 6,
140 cacheType = 7,
141 portConnectorType = 8,
142 systemSlots = 9,
143 onBoardDevicesType = 10,
144 oemStringsType = 11,
145 systemCconfigurationOptionsType = 12,
146 biosLanguageType = 13,
147 groupAssociatonsType = 14,
148 systemEventLogType = 15,
149 physicalMemoryArrayType = 16,
150 memoryDeviceType = 17,
151} SmbiosType;
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800152
153static constexpr uint8_t separateLen = 2;
154
155static inline uint8_t* smbiosNextPtr(uint8_t* smbiosDataIn)
156{
157 if (smbiosDataIn == nullptr)
158 {
159 return nullptr;
160 }
161 uint8_t* smbiosData = smbiosDataIn + *(smbiosDataIn + 1);
162 int len = 0;
163 while ((*smbiosData | *(smbiosData + 1)) != 0)
164 {
165 smbiosData++;
166 len++;
167 if (len >= mdrSMBIOSSize) // To avoid endless loop
168 {
169 return nullptr;
170 }
171 }
172 return smbiosData + separateLen;
173}
174
175// When first time run getSMBIOSTypePtr, need to send the RegionS[].regionData
176// to smbiosDataIn
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700177static inline uint8_t* getSMBIOSTypePtr(uint8_t* smbiosDataIn, uint8_t typeId,
178 size_t size = 0)
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800179{
180 if (smbiosDataIn == nullptr)
181 {
182 return nullptr;
183 }
184 char* smbiosData = reinterpret_cast<char*>(smbiosDataIn);
185 while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0'))
186 {
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700187 uint32_t len = *(smbiosData + 1);
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800188 if (*smbiosData != typeId)
189 {
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700190
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800191 smbiosData += len;
192 while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0'))
193 {
194 smbiosData++;
195 len++;
196 if (len >= mdrSMBIOSSize) // To avoid endless loop
197 {
198 return nullptr;
199 }
200 }
201 smbiosData += separateLen;
202 continue;
203 }
Zhikui Ren18a5ab92020-09-01 21:35:20 -0700204 if (len < size)
205 {
206 phosphor::logging::log<phosphor::logging::level::ERR>(
207 "Record size mismatch!");
208 return nullptr;
209 }
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800210 return reinterpret_cast<uint8_t*>(smbiosData);
211 }
212 return nullptr;
213}
214
215static inline std::string positionToString(uint8_t positionNum,
216 uint8_t structLen, uint8_t* dataIn)
217{
218 if (dataIn == nullptr)
219 {
220 return "";
221 }
222 uint16_t limit = mdrSMBIOSSize; // set a limit to avoid endless loop
223
224 char* target = reinterpret_cast<char*>(dataIn + structLen);
Kuiying Wang59bb9d92020-10-27 15:30:46 +0800225 if (target == nullptr)
226 {
227 return "";
228 }
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800229 for (uint8_t index = 1; index < positionNum; index++)
230 {
231 for (; *target != '\0'; target++)
232 {
233 limit--;
Kuiying Wang59bb9d92020-10-27 15:30:46 +0800234 // When target = dataIn + structLen + limit,
235 // following target++ will be nullptr
236 if (limit < 1 || target == nullptr)
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800237 {
238 return "";
239 }
240 }
241 target++;
Kuiying Wang59bb9d92020-10-27 15:30:46 +0800242 if (target == nullptr || *target == '\0')
Cheng C Yang43c6a1d2019-12-19 00:48:34 +0800243 {
244 return ""; // 0x00 0x00 means end of the entry.
245 }
246 }
247
248 std::string result = target;
249 return result;
250}