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