1 /*
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 "cpu.hpp"
18
19 #include <bitset>
20 #include <map>
21
22 namespace phosphor
23 {
24 namespace smbios
25 {
26
socket(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)27 void Cpu::socket(const uint8_t positionNum, const uint8_t structLen,
28 uint8_t* dataIn)
29 {
30 std::string result = positionToString(positionNum, structLen, dataIn);
31
32 processor::socket(result);
33
34 location::locationCode(result);
35 }
36
37 static constexpr uint8_t processorFamily2Indicator = 0xfe;
family(const uint8_t family,const uint16_t family2)38 void Cpu::family(const uint8_t family, const uint16_t family2)
39 {
40 std::map<uint8_t, const char*>::const_iterator it =
41 familyTable.find(family);
42 if (it == familyTable.end())
43 {
44 processor::family("Unknown Processor Family");
45 }
46 else if (it->first == processorFamily2Indicator)
47 {
48 std::map<uint16_t, const char*>::const_iterator it2 =
49 family2Table.find(family2);
50 if (it2 == family2Table.end())
51 {
52 processor::family("Unknown Processor Family");
53 }
54 else
55 {
56 processor::family(it2->second);
57 processor::effectiveFamily(family2);
58 }
59 }
60 else
61 {
62 processor::family(it->second);
63 processor::effectiveFamily(family);
64 }
65 }
66
manufacturer(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)67 void Cpu::manufacturer(const uint8_t positionNum, const uint8_t structLen,
68 uint8_t* dataIn)
69 {
70 std::string result = positionToString(positionNum, structLen, dataIn);
71
72 asset::manufacturer(result);
73 }
74
partNumber(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)75 void Cpu::partNumber(const uint8_t positionNum, const uint8_t structLen,
76 uint8_t* dataIn)
77 {
78 std::string result = positionToString(positionNum, structLen, dataIn);
79
80 asset::partNumber(result);
81 }
82
serialNumber(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)83 void Cpu::serialNumber(const uint8_t positionNum, const uint8_t structLen,
84 uint8_t* dataIn)
85 {
86 std::string result = positionToString(positionNum, structLen, dataIn);
87
88 asset::serialNumber(result);
89 }
90
version(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)91 void Cpu::version(const uint8_t positionNum, const uint8_t structLen,
92 uint8_t* dataIn)
93 {
94 std::string result;
95
96 result = positionToString(positionNum, structLen, dataIn);
97
98 rev::version(result);
99 }
100
characteristics(uint16_t value)101 void Cpu::characteristics(uint16_t value)
102 {
103 std::vector<processor::Capability> result;
104 std::optional<processor::Capability> cap;
105
106 std::bitset<16> charBits = value;
107 for (uint8_t index = 0; index < charBits.size(); index++)
108 {
109 if (charBits.test(index))
110 {
111 if ((cap = characteristicsTable[index]))
112 {
113 result.emplace_back(*cap);
114 }
115 }
116 }
117
118 processor::characteristics(result);
119 }
120
assetTagString(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)121 void Cpu::assetTagString(const uint8_t positionNum, const uint8_t structLen,
122 uint8_t* dataIn)
123 {
124 std::string result = positionToString(positionNum, structLen, dataIn);
125 assetTagType::assetTag(result);
126 }
127
128 static constexpr uint8_t maxOldVersionCount = 0xff;
infoUpdate(uint8_t * smbiosTableStorage,const std::string & motherboard)129 void Cpu::infoUpdate(uint8_t* smbiosTableStorage,
130 const std::string& motherboard)
131 {
132 storage = smbiosTableStorage;
133 motherboardPath = motherboard;
134
135 uint8_t* dataIn = storage;
136
137 dataIn = getSMBIOSTypePtr(dataIn, processorsType);
138 if (dataIn == nullptr)
139 {
140 return;
141 }
142
143 for (uint8_t index = 0; index < cpuNum; index++)
144 {
145 dataIn = smbiosNextPtr(dataIn);
146 if (dataIn == nullptr)
147 {
148 return;
149 }
150 dataIn = getSMBIOSTypePtr(dataIn, processorsType);
151 if (dataIn == nullptr)
152 {
153 return;
154 }
155 }
156
157 auto cpuInfo = reinterpret_cast<struct ProcessorInfo*>(dataIn);
158
159 socket(cpuInfo->socketDesignation, cpuInfo->length, dataIn); // offset 4h
160
161 constexpr uint32_t socketPopulatedMask = 1 << 6;
162 constexpr uint32_t statusMask = 0x07;
163 if ((cpuInfo->status & socketPopulatedMask) == 0)
164 {
165 // Don't attempt to fill in any other details if the CPU is not present.
166 present(false);
167 functional(false);
168 return;
169 }
170 present(true);
171 if ((cpuInfo->status & statusMask) == 1)
172 {
173 functional(true);
174 }
175 else
176 {
177 functional(false);
178 }
179
180 // this class is for type CPU //offset 5h
181 family(cpuInfo->family, cpuInfo->family2); // offset 6h and 28h
182 manufacturer(cpuInfo->manufacturer, cpuInfo->length,
183 dataIn); // offset 7h
184 id(cpuInfo->id); // offset 8h
185
186 // Step, EffectiveFamily, EffectiveModel computation for Intel processors.
187 std::map<uint8_t, const char*>::const_iterator it =
188 familyTable.find(cpuInfo->family);
189 if (it != familyTable.end())
190 {
191 std::string familyStr = it->second;
192 if ((familyStr.find(" Xeon ") != std::string::npos) ||
193 (familyStr.find(" Intel ") != std::string::npos) ||
194 (familyStr.find(" Zen ") != std::string::npos))
195 {
196 // Processor ID field
197 // SteppinID: 4;
198 // Model: 4;
199 // Family: 4;
200 // Type: 2;
201 // Reserved1: 2;
202 // XModel: 4;
203 // XFamily: 8;
204 // Reserved2: 4;
205 uint16_t cpuStep = cpuInfo->id & 0xf;
206 uint16_t cpuModel = (cpuInfo->id & 0xf0) >> 4;
207 uint16_t cpuFamily = (cpuInfo->id & 0xf00) >> 8;
208 uint16_t cpuXModel = (cpuInfo->id & 0xf0000) >> 16;
209 uint16_t cpuXFamily = (cpuInfo->id & 0xff00000) >> 20;
210 step(cpuStep);
211 if (cpuFamily == 0xf)
212 {
213 effectiveFamily(cpuXFamily + cpuFamily);
214 }
215 else
216 {
217 effectiveFamily(cpuFamily);
218 }
219 if (cpuFamily == 0x6 || cpuFamily == 0xf)
220 {
221 effectiveModel((cpuXModel << 4) | cpuModel);
222 }
223 else
224 {
225 effectiveModel(cpuModel);
226 }
227 }
228 }
229
230 version(cpuInfo->version, cpuInfo->length, dataIn); // offset 10h
231 maxSpeedInMhz(cpuInfo->maxSpeed); // offset 14h
232 serialNumber(cpuInfo->serialNum, cpuInfo->length,
233 dataIn); // offset 20h
234 assetTagString(cpuInfo->assetTag, cpuInfo->length,
235 dataIn); // offset 21h
236 partNumber(cpuInfo->partNum, cpuInfo->length,
237 dataIn); // offset 22h
238 if (cpuInfo->coreCount < maxOldVersionCount) // offset 23h or 2Ah
239 {
240 coreCount(cpuInfo->coreCount);
241 }
242 else
243 {
244 coreCount(cpuInfo->coreCount2);
245 }
246
247 if (cpuInfo->threadCount < maxOldVersionCount) // offset 25h or 2Eh)
248 {
249 threadCount(cpuInfo->threadCount);
250 }
251 else
252 {
253 threadCount(cpuInfo->threadCount2);
254 }
255
256 characteristics(cpuInfo->characteristics); // offset 26h
257
258 if (!motherboardPath.empty())
259 {
260 std::vector<std::tuple<std::string, std::string, std::string>> assocs;
261 assocs.emplace_back("chassis", "processors", motherboardPath);
262 association::associations(assocs);
263 }
264 }
265
266 } // namespace smbios
267 } // namespace phosphor
268