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