]> git.proxmox.com Git - mirror_edk2.git/blame - Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformationFunction.c
Vlv2TbltDevicePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / Vlv2TbltDevicePkg / SmBiosMiscDxe / MiscProcessorInformationFunction.c
CommitLineData
3cbfba02
DW
1/*++\r
2\r
3Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
4 \r\r
9dc8036d
MK
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
3cbfba02
DW
7 \r\r
8\r
9\r
10Module Name:\r
11\r
12 MiscProcessorInformationFunction.c\r
13\r
14Abstract:\r
15\r
16 Onboard processor information boot time changes.\r
17 SMBIOS type 4.\r
18\r
19--*/\r
20\r
21#include "CommonHeader.h"\r
22\r
23#include "MiscSubclassDriver.h"\r
24\r
25#include <Protocol/MpService.h>\r
26#include <Protocol/DataHub.h>\r
27#include <Guid/DataHubRecords.h>\r
28#include <Library/CpuIA32.h>\r
29\r
30#define EfiProcessorFamilyIntelAtomProcessor 0x2B\r
31\r
32EFI_GUID mProcessorProducerGuid;\r
33\r
34\r
35/**\r
36 Get cache SMBIOS record handle.\r
37\r
38 @param Smbios Pointer to SMBIOS protocol instance.\r
39 @param CacheLevel Level of cache, starting from one.\r
40 @param Handle Returned record handle.\r
41\r
42**/\r
43\r
44VOID\r
45GetCacheHandle (\r
46 IN EFI_SMBIOS_PROTOCOL *Smbios,\r
47 IN UINT8 CacheLevel,\r
48 OUT EFI_SMBIOS_HANDLE *Handle\r
49 )\r
50{\r
51 UINT16 CacheConfig;\r
52 EFI_STATUS Status;\r
53 EFI_SMBIOS_TYPE RecordType;\r
54 EFI_SMBIOS_TABLE_HEADER *Buffer;\r
55\r
56 *Handle = 0;\r
57 RecordType = EFI_SMBIOS_TYPE_CACHE_INFORMATION;\r
58\r
59 do {\r
60 Status = Smbios->GetNext (\r
61 Smbios,\r
62 Handle,\r
63 &RecordType,\r
64 &Buffer,\r
65 NULL\r
66 );\r
67 if (!EFI_ERROR(Status)) {\r
68 CacheConfig = *(UINT16*)((UINT8*)Buffer + 5);\r
69 if ((CacheConfig & 0x7) == (CacheLevel -1) ) {\r
70 return;\r
71 }\r
72 }\r
73 } while (!EFI_ERROR(Status));\r
74\r
75 *Handle = 0xFFFF;\r
76}\r
77\r
78\r
79/**\r
80 This function makes boot time changes to the contents of the\r
81 MiscProcessorInformation (Type 4).\r
82\r
83 @param RecordData Pointer to copy of RecordData from the Data Table.\r
84\r
85 @retval EFI_SUCCESS All parameters were valid.\r
86 @retval EFI_UNSUPPORTED Unexpected RecordType value.\r
87 @retval EFI_INVALID_PARAMETER Invalid parameter was found.\r
88\r
89**/\r
90UINT32\r
91ConvertBase10ToRaw (\r
92 IN EFI_EXP_BASE10_DATA *Data)\r
93{\r
94 UINTN Index;\r
95 UINT32 RawData;\r
96\r
97 RawData = Data->Value;\r
98 for (Index = 0; Index < (UINTN) Data->Exponent; Index++) {\r
99 RawData *= 10;\r
100 }\r
101\r
102 return RawData;\r
103}\r
104\r
105#define BSEL_CR_OVERCLOCK_CONTROL 0xCD\r
106#define FUSE_BSEL_MASK 0x03\r
107\r
108\r
109\r
110UINT16 miFSBFrequencyTable[4] = {\r
111 83, // 83.3MHz\r
112 100, // 100MHz\r
113 133, // 133MHz\r
114 117 // 116.7MHz\r
115};\r
116\r
117/**\r
118 Determine the processor core frequency\r
119\r
120 @param None\r
121\r
122 @retval Processor core frequency multiplied by 3\r
123\r
124\r
125**/\r
126UINT16\r
127DetermineiFsbFromMsr (\r
128 VOID\r
129 )\r
130{\r
131 //\r
132 // Determine the processor core frequency\r
133 //\r
134 UINT64 Temp;\r
135 Temp = (EfiReadMsr (BSEL_CR_OVERCLOCK_CONTROL)) & FUSE_BSEL_MASK;\r
136 return miFSBFrequencyTable[(UINT32)(Temp)];\r
137\r
138}\r
139\r
140MISC_SMBIOS_TABLE_FUNCTION (MiscProcessorInformation)\r
141{\r
142 CHAR8 *OptionalStrStart;\r
143 EFI_STRING SerialNumber;\r
144 CHAR16 *Version=NULL;\r
145 CHAR16 *Manufacturer=NULL;\r
146 CHAR16 *Socket=NULL;\r
147 CHAR16 *AssetTag=NULL;\r
148 CHAR16 *PartNumber=NULL;\r
149 UINTN SerialNumberStrLen=0;\r
150 UINTN VersionStrLen=0;\r
151 UINTN ManufacturerStrLen=0;\r
152 UINTN SocketStrLen=0;\r
153 UINTN AssetTagStrLen=0;\r
154 UINTN PartNumberStrLen=0;\r
155 UINTN ProcessorVoltage=0xAE;\r
156 UINT32 Eax01;\r
157 UINT32 Ebx01;\r
158 UINT32 Ecx01;\r
159 UINT32 Edx01;\r
160 STRING_REF TokenToGet;\r
161 EFI_STATUS Status;\r
162 EFI_SMBIOS_HANDLE SmbiosHandle;\r
163 SMBIOS_TABLE_TYPE4 *SmbiosRecord;\r
164 EFI_CPU_DATA_RECORD *ForType4InputData;\r
165 UINT16 L1CacheHandle=0;\r
166 UINT16 L2CacheHandle=0;\r
167 UINT16 L3CacheHandle=0;\r
168 UINTN NumberOfEnabledProcessors=0 ;\r
169 UINTN NumberOfProcessors=0;\r
170 UINT64 Frequency = 0;\r
171 EFI_MP_SERVICES_PROTOCOL *MpService;\r
172 EFI_DATA_HUB_PROTOCOL *DataHub;\r
173 UINT64 MonotonicCount;\r
174 EFI_DATA_RECORD_HEADER *Record;\r
175 EFI_SUBCLASS_TYPE1_HEADER *DataHeader;\r
176 UINT8 *SrcData;\r
3cbfba02
DW
177 EFI_PROCESSOR_VERSION_DATA *ProcessorVersion;\r
178 CHAR16 *NewStringToken;\r
179 STRING_REF TokenToUpdate;\r
180 PROCESSOR_ID_DATA *ProcessorId = NULL;\r
181\r
182\r
183 //\r
184 // First check for invalid parameters.\r
185 //\r
186 if (RecordData == NULL) {\r
187 return EFI_INVALID_PARAMETER;\r
188 }\r
189\r
190 ForType4InputData = (EFI_CPU_DATA_RECORD *)RecordData;\r
191\r
192 ProcessorId = AllocateZeroPool(sizeof(PROCESSOR_ID_DATA));\r
193 if (ProcessorId == NULL) {\r
194 return EFI_INVALID_PARAMETER;\r
195 }\r
196\r
197 //\r
198 // Get the Data Hub Protocol. Assume only one instance\r
199 //\r
200 Status = gBS->LocateProtocol (\r
201 &gEfiDataHubProtocolGuid,\r
202 NULL,\r
203 (VOID **)&DataHub\r
204 );\r
205 ASSERT_EFI_ERROR(Status);\r
206\r
207 MonotonicCount = 0;\r
208 Record = NULL;\r
209\r
210 do {\r
211 Status = DataHub->GetNextRecord (\r
212 DataHub,\r
213 &MonotonicCount,\r
214 NULL,\r
215 &Record\r
216 );\r
217 if (!EFI_ERROR(Status)) {\r
218 if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {\r
219\r
220 DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *)(Record + 1);\r
221 SrcData = (UINT8 *)(DataHeader + 1);\r
3cbfba02
DW
222\r
223 //\r
224 // Processor\r
225 //\r
226 if (CompareGuid(&Record->DataRecordGuid, &gEfiProcessorSubClassGuid)) {\r
227 CopyMem (&mProcessorProducerGuid, &Record->ProducerName, sizeof(EFI_GUID));\r
228 switch (DataHeader->RecordType) {\r
229 case ProcessorVoltageRecordType:\r
230 ProcessorVoltage = (((EFI_EXP_BASE10_DATA *)SrcData)->Value)/100 + 0x80;\r
231 break;\r
232 case ProcessorCoreFrequencyRecordType:\r
233 DEBUG ((EFI_D_ERROR, "ProcessorCoreFrequencyRecordType SrcData1 =%d\n", ConvertBase10ToRaw((EFI_EXP_BASE10_DATA *)SrcData)/1000000));\r
234 Frequency = (ConvertBase10ToRaw((EFI_EXP_BASE10_DATA *)SrcData)/1000000);\r
235 break;\r
236 case ProcessorVersionRecordType:\r
237 ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *)SrcData;\r
238 NewStringToken = HiiGetPackageString(&mProcessorProducerGuid, *ProcessorVersion, NULL);\r
239 TokenToUpdate = (STRING_REF)STR_MISC_PROCESSOR_VERSION;\r
240 HiiSetString(mHiiHandle, TokenToUpdate, NewStringToken, NULL);\r
241 break;\r
242 default:\r
243 break;\r
244 }\r
245 }\r
246 }\r
247 }\r
248 } while (!EFI_ERROR(Status) && (MonotonicCount != 0));\r
249\r
250 //\r
251 // Token to get for Socket Name\r
252 //\r
253 TokenToGet = STRING_TOKEN (STR_MISC_SOCKET_NAME);\r
254 Socket = SmbiosMiscGetString (TokenToGet);\r
255 SocketStrLen = StrLen(Socket);\r
256 if (SocketStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
257 return EFI_UNSUPPORTED;\r
258 }\r
259\r
260 //\r
261 // Token to get for Processor Manufacturer\r
262 //\r
263 TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_MAUFACTURER);\r
264 Manufacturer = SmbiosMiscGetString (TokenToGet);\r
265 ManufacturerStrLen = StrLen(Manufacturer);\r
266 if (ManufacturerStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
267 return EFI_UNSUPPORTED;\r
268 }\r
269\r
270 //\r
271 // Token to get for Processor Version\r
272 //\r
273 TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_VERSION);\r
274 Version = SmbiosMiscGetString (TokenToGet);\r
275 VersionStrLen = StrLen(Version);\r
276 if (VersionStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
277 return EFI_UNSUPPORTED;\r
278 }\r
279\r
280 //\r
281 // Token to get for Serial Number\r
282 //\r
283 TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_SERIAL_NUMBER);\r
284 SerialNumber = SmbiosMiscGetString (TokenToGet);\r
285 SerialNumberStrLen = StrLen(SerialNumber);\r
286 if (SerialNumberStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
287 return EFI_UNSUPPORTED;\r
288 }\r
289\r
290 //\r
291 // Token to get for Assert Tag Information\r
292 //\r
293 TokenToGet = STRING_TOKEN (STR_MISC_ASSERT_TAG_DATA);\r
294 AssetTag = SmbiosMiscGetString (TokenToGet);\r
295 AssetTagStrLen = StrLen(AssetTag);\r
296 if (AssetTagStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
297 return EFI_UNSUPPORTED;\r
298 }\r
299\r
300 //\r
301 // Token to get for part number Information\r
302 //\r
303 TokenToGet = STRING_TOKEN (STR_MISC_PART_NUMBER);\r
304 PartNumber = SmbiosMiscGetString (TokenToGet);\r
305 PartNumberStrLen = StrLen(PartNumber);\r
306 if (PartNumberStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
307 return EFI_UNSUPPORTED;\r
308 }\r
309\r
310 //\r
311 // Two zeros following the last string.\r
312 //\r
313 SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE4) + AssetTagStrLen + 1 + SocketStrLen + 1+ ManufacturerStrLen +1 + VersionStrLen+ 1+ SerialNumberStrLen + 1 + PartNumberStrLen+ 1 + 1);\r
314\r
315 SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;\r
316 SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE4);\r
317\r
318 //\r
319 // Make handle chosen by smbios protocol.add automatically.\r
320 //\r
321 SmbiosRecord->Hdr.Handle = 0;\r
322\r
323 SmbiosRecord-> Socket= 1;\r
324 SmbiosRecord -> ProcessorManufacture = 2;\r
325 SmbiosRecord -> ProcessorVersion = 3;\r
326 SmbiosRecord ->SerialNumber =4;\r
327\r
328 SmbiosRecord-> AssetTag= 5;\r
329 SmbiosRecord-> PartNumber= 6;\r
330\r
331 //\r
332 // Processor Type\r
333 //\r
334 ForType4InputData-> VariableRecord.ProcessorType= EfiCentralProcessor;\r
335 SmbiosRecord -> ProcessorType = ForType4InputData-> VariableRecord.ProcessorType;\r
336\r
337 //\r
338 // Processor Family\r
339 //\r
340 ForType4InputData-> VariableRecord.ProcessorFamily= EfiProcessorFamilyIntelAtomProcessor; //0x2B;;\r
341 SmbiosRecord -> ProcessorFamily = ForType4InputData-> VariableRecord.ProcessorFamily;\r
342 SmbiosRecord -> ExternalClock = DetermineiFsbFromMsr();\r
343\r
344 //\r
345 // Processor ID\r
346 //\r
347 AsmCpuid(0x001, &Eax01, &Ebx01, &Ecx01, &Edx01);\r
348 ProcessorId->Signature = *(PROCESSOR_SIGNATURE *)&Eax01;\r
349 ProcessorId->FeatureFlags = *(PROCESSOR_FEATURE_FLAGS *)&Edx01;\r
350 SmbiosRecord -> ProcessorId = *(PROCESSOR_ID_DATA *)ProcessorId;\r
351\r
352 //\r
353 // Processor Voltage\r
354 //\r
355 ForType4InputData-> VariableRecord.ProcessorVoltage= *(EFI_PROCESSOR_VOLTAGE_DATA *)&ProcessorVoltage;\r
356 SmbiosRecord -> Voltage = *(PROCESSOR_VOLTAGE *) &(ForType4InputData-> VariableRecord.ProcessorVoltage);\r
357\r
358 //\r
359 // Status\r
360 //\r
361 ForType4InputData-> VariableRecord.ProcessorHealthStatus= 0x41;//0x41;\r
362 SmbiosRecord -> Status = ForType4InputData-> VariableRecord.ProcessorHealthStatus;\r
363\r
364 //\r
365 // Processor Upgrade\r
366 //\r
367 SmbiosRecord -> ProcessorUpgrade = 0x008;\r
368\r
369 //\r
370 // Processor Family 2\r
371 //\r
372 SmbiosRecord -> ProcessorFamily2 = ForType4InputData-> VariableRecord.ProcessorFamily;\r
373\r
374 //\r
375 // Processor speed\r
376 //\r
377 SmbiosRecord-> CurrentSpeed = *(UINT16*) & Frequency;\r
378 SmbiosRecord-> MaxSpeed = *(UINT16*) & Frequency;\r
379\r
380 //\r
381 // Processor Characteristics\r
382 //\r
383 AsmCpuid(0x8000000, NULL, NULL, NULL, &Edx01);\r
384 Edx01= Edx01 >> 28;\r
385 Edx01 &= 0x01;\r
386 SmbiosRecord-> ProcessorCharacteristics= (UINT16)Edx01;\r
387\r
388 //\r
389 // Processor Core Count and Enabled core count\r
390 //\r
391 Status = gBS->LocateProtocol (\r
392 &gEfiMpServiceProtocolGuid,\r
393 NULL,\r
394 (void **)&MpService\r
395 );\r
396 if (!EFI_ERROR (Status)) {\r
397 //\r
398 // Determine the number of processors\r
399 //\r
400 MpService->GetNumberOfProcessors (\r
401 MpService,\r
402 &NumberOfProcessors,\r
403 &NumberOfEnabledProcessors\r
404 );\r
405 }\r
406 SmbiosRecord-> CoreCount= (UINT8)NumberOfProcessors;\r
407 SmbiosRecord-> EnabledCoreCount= (UINT8)NumberOfEnabledProcessors;\r
408 SmbiosRecord-> ThreadCount= (UINT8)NumberOfEnabledProcessors;\r
409 SmbiosRecord-> ProcessorCharacteristics = 0x2; // Unknown\r
410\r
411 //\r
412 // Processor Cache Handle\r
413 //\r
414 GetCacheHandle( Smbios,1, &L1CacheHandle);\r
415 GetCacheHandle( Smbios,2, &L2CacheHandle);\r
416 GetCacheHandle( Smbios,3, &L3CacheHandle);\r
417\r
418 //\r
419 // Updating Cache Handle Information\r
420 //\r
421 SmbiosRecord->L1CacheHandle = L1CacheHandle;\r
422 SmbiosRecord->L2CacheHandle = L2CacheHandle;\r
423 SmbiosRecord->L3CacheHandle = L3CacheHandle;\r
424\r
425 OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);\r
426 UnicodeStrToAsciiStr(Socket, OptionalStrStart);\r
427 UnicodeStrToAsciiStr(Manufacturer, OptionalStrStart + SocketStrLen + 1);\r
428 UnicodeStrToAsciiStr(Version, OptionalStrStart + SocketStrLen + 1 + ManufacturerStrLen+ 1);\r
429 UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + SocketStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1);\r
430 UnicodeStrToAsciiStr(AssetTag, OptionalStrStart + SerialNumberStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1 + SocketStrLen + 1);\r
431 UnicodeStrToAsciiStr(PartNumber, OptionalStrStart + SerialNumberStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1 + SocketStrLen + 1 + AssetTagStrLen + 1 );\r
432\r
433 //\r
434 // Now we have got the full Smbios record, call Smbios protocol to add this record.\r
435 //\r
436 SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
437 Status = Smbios-> Add(\r
438 Smbios,\r
439 NULL,\r
440 &SmbiosHandle,\r
441 (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord\r
442 );\r
443 if (EFI_ERROR (Status)) return Status;\r
444 FreePool(SmbiosRecord);\r
445 return Status;\r
446\r
447}\r
448\r