]> git.proxmox.com Git - mirror_edk2.git/blame - Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformationFunction.c
Vlv2TbltDevicePkg:Signal EndOfDxe Event.
[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
182 UINT32 SrcDataSize;\r
183 EFI_PROCESSOR_VERSION_DATA *ProcessorVersion;\r
184 CHAR16 *NewStringToken;\r
185 STRING_REF TokenToUpdate;\r
186 PROCESSOR_ID_DATA *ProcessorId = NULL;\r
187\r
188\r
189 //\r
190 // First check for invalid parameters.\r
191 //\r
192 if (RecordData == NULL) {\r
193 return EFI_INVALID_PARAMETER;\r
194 }\r
195\r
196 ForType4InputData = (EFI_CPU_DATA_RECORD *)RecordData;\r
197\r
198 ProcessorId = AllocateZeroPool(sizeof(PROCESSOR_ID_DATA));\r
199 if (ProcessorId == NULL) {\r
200 return EFI_INVALID_PARAMETER;\r
201 }\r
202\r
203 //\r
204 // Get the Data Hub Protocol. Assume only one instance\r
205 //\r
206 Status = gBS->LocateProtocol (\r
207 &gEfiDataHubProtocolGuid,\r
208 NULL,\r
209 (VOID **)&DataHub\r
210 );\r
211 ASSERT_EFI_ERROR(Status);\r
212\r
213 MonotonicCount = 0;\r
214 Record = NULL;\r
215\r
216 do {\r
217 Status = DataHub->GetNextRecord (\r
218 DataHub,\r
219 &MonotonicCount,\r
220 NULL,\r
221 &Record\r
222 );\r
223 if (!EFI_ERROR(Status)) {\r
224 if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {\r
225\r
226 DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *)(Record + 1);\r
227 SrcData = (UINT8 *)(DataHeader + 1);\r
228 SrcDataSize = Record->RecordSize - Record->HeaderSize - sizeof (EFI_SUBCLASS_TYPE1_HEADER);\r
229\r
230 //\r
231 // Processor\r
232 //\r
233 if (CompareGuid(&Record->DataRecordGuid, &gEfiProcessorSubClassGuid)) {\r
234 CopyMem (&mProcessorProducerGuid, &Record->ProducerName, sizeof(EFI_GUID));\r
235 switch (DataHeader->RecordType) {\r
236 case ProcessorVoltageRecordType:\r
237 ProcessorVoltage = (((EFI_EXP_BASE10_DATA *)SrcData)->Value)/100 + 0x80;\r
238 break;\r
239 case ProcessorCoreFrequencyRecordType:\r
240 DEBUG ((EFI_D_ERROR, "ProcessorCoreFrequencyRecordType SrcData1 =%d\n", ConvertBase10ToRaw((EFI_EXP_BASE10_DATA *)SrcData)/1000000));\r
241 Frequency = (ConvertBase10ToRaw((EFI_EXP_BASE10_DATA *)SrcData)/1000000);\r
242 break;\r
243 case ProcessorVersionRecordType:\r
244 ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *)SrcData;\r
245 NewStringToken = HiiGetPackageString(&mProcessorProducerGuid, *ProcessorVersion, NULL);\r
246 TokenToUpdate = (STRING_REF)STR_MISC_PROCESSOR_VERSION;\r
247 HiiSetString(mHiiHandle, TokenToUpdate, NewStringToken, NULL);\r
248 break;\r
249 default:\r
250 break;\r
251 }\r
252 }\r
253 }\r
254 }\r
255 } while (!EFI_ERROR(Status) && (MonotonicCount != 0));\r
256\r
257 //\r
258 // Token to get for Socket Name\r
259 //\r
260 TokenToGet = STRING_TOKEN (STR_MISC_SOCKET_NAME);\r
261 Socket = SmbiosMiscGetString (TokenToGet);\r
262 SocketStrLen = StrLen(Socket);\r
263 if (SocketStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
264 return EFI_UNSUPPORTED;\r
265 }\r
266\r
267 //\r
268 // Token to get for Processor Manufacturer\r
269 //\r
270 TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_MAUFACTURER);\r
271 Manufacturer = SmbiosMiscGetString (TokenToGet);\r
272 ManufacturerStrLen = StrLen(Manufacturer);\r
273 if (ManufacturerStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
274 return EFI_UNSUPPORTED;\r
275 }\r
276\r
277 //\r
278 // Token to get for Processor Version\r
279 //\r
280 TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_VERSION);\r
281 Version = SmbiosMiscGetString (TokenToGet);\r
282 VersionStrLen = StrLen(Version);\r
283 if (VersionStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
284 return EFI_UNSUPPORTED;\r
285 }\r
286\r
287 //\r
288 // Token to get for Serial Number\r
289 //\r
290 TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_SERIAL_NUMBER);\r
291 SerialNumber = SmbiosMiscGetString (TokenToGet);\r
292 SerialNumberStrLen = StrLen(SerialNumber);\r
293 if (SerialNumberStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
294 return EFI_UNSUPPORTED;\r
295 }\r
296\r
297 //\r
298 // Token to get for Assert Tag Information\r
299 //\r
300 TokenToGet = STRING_TOKEN (STR_MISC_ASSERT_TAG_DATA);\r
301 AssetTag = SmbiosMiscGetString (TokenToGet);\r
302 AssetTagStrLen = StrLen(AssetTag);\r
303 if (AssetTagStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
304 return EFI_UNSUPPORTED;\r
305 }\r
306\r
307 //\r
308 // Token to get for part number Information\r
309 //\r
310 TokenToGet = STRING_TOKEN (STR_MISC_PART_NUMBER);\r
311 PartNumber = SmbiosMiscGetString (TokenToGet);\r
312 PartNumberStrLen = StrLen(PartNumber);\r
313 if (PartNumberStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
314 return EFI_UNSUPPORTED;\r
315 }\r
316\r
317 //\r
318 // Two zeros following the last string.\r
319 //\r
320 SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE4) + AssetTagStrLen + 1 + SocketStrLen + 1+ ManufacturerStrLen +1 + VersionStrLen+ 1+ SerialNumberStrLen + 1 + PartNumberStrLen+ 1 + 1);\r
321\r
322 SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;\r
323 SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE4);\r
324\r
325 //\r
326 // Make handle chosen by smbios protocol.add automatically.\r
327 //\r
328 SmbiosRecord->Hdr.Handle = 0;\r
329\r
330 SmbiosRecord-> Socket= 1;\r
331 SmbiosRecord -> ProcessorManufacture = 2;\r
332 SmbiosRecord -> ProcessorVersion = 3;\r
333 SmbiosRecord ->SerialNumber =4;\r
334\r
335 SmbiosRecord-> AssetTag= 5;\r
336 SmbiosRecord-> PartNumber= 6;\r
337\r
338 //\r
339 // Processor Type\r
340 //\r
341 ForType4InputData-> VariableRecord.ProcessorType= EfiCentralProcessor;\r
342 SmbiosRecord -> ProcessorType = ForType4InputData-> VariableRecord.ProcessorType;\r
343\r
344 //\r
345 // Processor Family\r
346 //\r
347 ForType4InputData-> VariableRecord.ProcessorFamily= EfiProcessorFamilyIntelAtomProcessor; //0x2B;;\r
348 SmbiosRecord -> ProcessorFamily = ForType4InputData-> VariableRecord.ProcessorFamily;\r
349 SmbiosRecord -> ExternalClock = DetermineiFsbFromMsr();\r
350\r
351 //\r
352 // Processor ID\r
353 //\r
354 AsmCpuid(0x001, &Eax01, &Ebx01, &Ecx01, &Edx01);\r
355 ProcessorId->Signature = *(PROCESSOR_SIGNATURE *)&Eax01;\r
356 ProcessorId->FeatureFlags = *(PROCESSOR_FEATURE_FLAGS *)&Edx01;\r
357 SmbiosRecord -> ProcessorId = *(PROCESSOR_ID_DATA *)ProcessorId;\r
358\r
359 //\r
360 // Processor Voltage\r
361 //\r
362 ForType4InputData-> VariableRecord.ProcessorVoltage= *(EFI_PROCESSOR_VOLTAGE_DATA *)&ProcessorVoltage;\r
363 SmbiosRecord -> Voltage = *(PROCESSOR_VOLTAGE *) &(ForType4InputData-> VariableRecord.ProcessorVoltage);\r
364\r
365 //\r
366 // Status\r
367 //\r
368 ForType4InputData-> VariableRecord.ProcessorHealthStatus= 0x41;//0x41;\r
369 SmbiosRecord -> Status = ForType4InputData-> VariableRecord.ProcessorHealthStatus;\r
370\r
371 //\r
372 // Processor Upgrade\r
373 //\r
374 SmbiosRecord -> ProcessorUpgrade = 0x008;\r
375\r
376 //\r
377 // Processor Family 2\r
378 //\r
379 SmbiosRecord -> ProcessorFamily2 = ForType4InputData-> VariableRecord.ProcessorFamily;\r
380\r
381 //\r
382 // Processor speed\r
383 //\r
384 SmbiosRecord-> CurrentSpeed = *(UINT16*) & Frequency;\r
385 SmbiosRecord-> MaxSpeed = *(UINT16*) & Frequency;\r
386\r
387 //\r
388 // Processor Characteristics\r
389 //\r
390 AsmCpuid(0x8000000, NULL, NULL, NULL, &Edx01);\r
391 Edx01= Edx01 >> 28;\r
392 Edx01 &= 0x01;\r
393 SmbiosRecord-> ProcessorCharacteristics= (UINT16)Edx01;\r
394\r
395 //\r
396 // Processor Core Count and Enabled core count\r
397 //\r
398 Status = gBS->LocateProtocol (\r
399 &gEfiMpServiceProtocolGuid,\r
400 NULL,\r
401 (void **)&MpService\r
402 );\r
403 if (!EFI_ERROR (Status)) {\r
404 //\r
405 // Determine the number of processors\r
406 //\r
407 MpService->GetNumberOfProcessors (\r
408 MpService,\r
409 &NumberOfProcessors,\r
410 &NumberOfEnabledProcessors\r
411 );\r
412 }\r
413 SmbiosRecord-> CoreCount= (UINT8)NumberOfProcessors;\r
414 SmbiosRecord-> EnabledCoreCount= (UINT8)NumberOfEnabledProcessors;\r
415 SmbiosRecord-> ThreadCount= (UINT8)NumberOfEnabledProcessors;\r
416 SmbiosRecord-> ProcessorCharacteristics = 0x2; // Unknown\r
417\r
418 //\r
419 // Processor Cache Handle\r
420 //\r
421 GetCacheHandle( Smbios,1, &L1CacheHandle);\r
422 GetCacheHandle( Smbios,2, &L2CacheHandle);\r
423 GetCacheHandle( Smbios,3, &L3CacheHandle);\r
424\r
425 //\r
426 // Updating Cache Handle Information\r
427 //\r
428 SmbiosRecord->L1CacheHandle = L1CacheHandle;\r
429 SmbiosRecord->L2CacheHandle = L2CacheHandle;\r
430 SmbiosRecord->L3CacheHandle = L3CacheHandle;\r
431\r
432 OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);\r
433 UnicodeStrToAsciiStr(Socket, OptionalStrStart);\r
434 UnicodeStrToAsciiStr(Manufacturer, OptionalStrStart + SocketStrLen + 1);\r
435 UnicodeStrToAsciiStr(Version, OptionalStrStart + SocketStrLen + 1 + ManufacturerStrLen+ 1);\r
436 UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + SocketStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1);\r
437 UnicodeStrToAsciiStr(AssetTag, OptionalStrStart + SerialNumberStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1 + SocketStrLen + 1);\r
438 UnicodeStrToAsciiStr(PartNumber, OptionalStrStart + SerialNumberStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1 + SocketStrLen + 1 + AssetTagStrLen + 1 );\r
439\r
440 //\r
441 // Now we have got the full Smbios record, call Smbios protocol to add this record.\r
442 //\r
443 SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
444 Status = Smbios-> Add(\r
445 Smbios,\r
446 NULL,\r
447 &SmbiosHandle,\r
448 (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord\r
449 );\r
450 if (EFI_ERROR (Status)) return Status;\r
451 FreePool(SmbiosRecord);\r
452 return Status;\r
453\r
454}\r
455\r