3 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 MiscProcessorInformationFunction.c
16 Onboard processor information boot time changes.
21 #include "CommonHeader.h"
23 #include "MiscSubclassDriver.h"
25 #include <Protocol/MpService.h>
26 #include <Protocol/DataHub.h>
27 #include <Guid/DataHubRecords.h>
28 #include <Library/CpuIA32.h>
30 #define EfiProcessorFamilyIntelAtomProcessor 0x2B
32 EFI_GUID mProcessorProducerGuid
;
36 Get cache SMBIOS record handle.
38 @param Smbios Pointer to SMBIOS protocol instance.
39 @param CacheLevel Level of cache, starting from one.
40 @param Handle Returned record handle.
46 IN EFI_SMBIOS_PROTOCOL
*Smbios
,
48 OUT EFI_SMBIOS_HANDLE
*Handle
53 EFI_SMBIOS_TYPE RecordType
;
54 EFI_SMBIOS_TABLE_HEADER
*Buffer
;
57 RecordType
= EFI_SMBIOS_TYPE_CACHE_INFORMATION
;
60 Status
= Smbios
->GetNext (
67 if (!EFI_ERROR(Status
)) {
68 CacheConfig
= *(UINT16
*)((UINT8
*)Buffer
+ 5);
69 if ((CacheConfig
& 0x7) == (CacheLevel
-1) ) {
73 } while (!EFI_ERROR(Status
));
80 This function makes boot time changes to the contents of the
81 MiscProcessorInformation (Type 4).
83 @param RecordData Pointer to copy of RecordData from the Data Table.
85 @retval EFI_SUCCESS All parameters were valid.
86 @retval EFI_UNSUPPORTED Unexpected RecordType value.
87 @retval EFI_INVALID_PARAMETER Invalid parameter was found.
92 IN EFI_EXP_BASE10_DATA
*Data
)
97 RawData
= Data
->Value
;
98 for (Index
= 0; Index
< (UINTN
) Data
->Exponent
; Index
++) {
105 #define BSEL_CR_OVERCLOCK_CONTROL 0xCD
106 #define FUSE_BSEL_MASK 0x03
110 UINT16 miFSBFrequencyTable
[4] = {
118 Determine the processor core frequency
122 @retval Processor core frequency multiplied by 3
127 DetermineiFsbFromMsr (
132 // Determine the processor core frequency
135 Temp
= (EfiReadMsr (BSEL_CR_OVERCLOCK_CONTROL
)) & FUSE_BSEL_MASK
;
136 return miFSBFrequencyTable
[(UINT32
)(Temp
)];
140 MISC_SMBIOS_TABLE_FUNCTION (MiscProcessorInformation
)
142 CHAR8
*OptionalStrStart
;
143 EFI_STRING SerialNumber
;
144 CHAR16
*Version
=NULL
;
145 CHAR16
*Manufacturer
=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;
160 STRING_REF TokenToGet
;
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
;
177 EFI_PROCESSOR_VERSION_DATA
*ProcessorVersion
;
178 CHAR16
*NewStringToken
;
179 STRING_REF TokenToUpdate
;
180 PROCESSOR_ID_DATA
*ProcessorId
= NULL
;
184 // First check for invalid parameters.
186 if (RecordData
== NULL
) {
187 return EFI_INVALID_PARAMETER
;
190 ForType4InputData
= (EFI_CPU_DATA_RECORD
*)RecordData
;
192 ProcessorId
= AllocateZeroPool(sizeof(PROCESSOR_ID_DATA
));
193 if (ProcessorId
== NULL
) {
194 return EFI_INVALID_PARAMETER
;
198 // Get the Data Hub Protocol. Assume only one instance
200 Status
= gBS
->LocateProtocol (
201 &gEfiDataHubProtocolGuid
,
205 ASSERT_EFI_ERROR(Status
);
211 Status
= DataHub
->GetNextRecord (
217 if (!EFI_ERROR(Status
)) {
218 if (Record
->DataRecordClass
== EFI_DATA_RECORD_CLASS_DATA
) {
220 DataHeader
= (EFI_SUBCLASS_TYPE1_HEADER
*)(Record
+ 1);
221 SrcData
= (UINT8
*)(DataHeader
+ 1);
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;
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);
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
);
248 } while (!EFI_ERROR(Status
) && (MonotonicCount
!= 0));
251 // Token to get for Socket Name
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
;
261 // Token to get for Processor Manufacturer
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
;
271 // Token to get for Processor Version
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
;
281 // Token to get for Serial Number
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
;
291 // Token to get for Assert Tag Information
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
;
301 // Token to get for part number Information
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
;
311 // Two zeros following the last string.
313 SmbiosRecord
= AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE4
) + AssetTagStrLen
+ 1 + SocketStrLen
+ 1+ ManufacturerStrLen
+1 + VersionStrLen
+ 1+ SerialNumberStrLen
+ 1 + PartNumberStrLen
+ 1 + 1);
315 SmbiosRecord
->Hdr
.Type
= EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION
;
316 SmbiosRecord
->Hdr
.Length
= sizeof (SMBIOS_TABLE_TYPE4
);
319 // Make handle chosen by smbios protocol.add automatically.
321 SmbiosRecord
->Hdr
.Handle
= 0;
323 SmbiosRecord
-> Socket
= 1;
324 SmbiosRecord
-> ProcessorManufacture
= 2;
325 SmbiosRecord
-> ProcessorVersion
= 3;
326 SmbiosRecord
->SerialNumber
=4;
328 SmbiosRecord
-> AssetTag
= 5;
329 SmbiosRecord
-> PartNumber
= 6;
334 ForType4InputData
-> VariableRecord
.ProcessorType
= EfiCentralProcessor
;
335 SmbiosRecord
-> ProcessorType
= ForType4InputData
-> VariableRecord
.ProcessorType
;
340 ForType4InputData
-> VariableRecord
.ProcessorFamily
= EfiProcessorFamilyIntelAtomProcessor
; //0x2B;;
341 SmbiosRecord
-> ProcessorFamily
= ForType4InputData
-> VariableRecord
.ProcessorFamily
;
342 SmbiosRecord
-> ExternalClock
= DetermineiFsbFromMsr();
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
;
355 ForType4InputData
-> VariableRecord
.ProcessorVoltage
= *(EFI_PROCESSOR_VOLTAGE_DATA
*)&ProcessorVoltage
;
356 SmbiosRecord
-> Voltage
= *(PROCESSOR_VOLTAGE
*) &(ForType4InputData
-> VariableRecord
.ProcessorVoltage
);
361 ForType4InputData
-> VariableRecord
.ProcessorHealthStatus
= 0x41;//0x41;
362 SmbiosRecord
-> Status
= ForType4InputData
-> VariableRecord
.ProcessorHealthStatus
;
367 SmbiosRecord
-> ProcessorUpgrade
= 0x008;
370 // Processor Family 2
372 SmbiosRecord
-> ProcessorFamily2
= ForType4InputData
-> VariableRecord
.ProcessorFamily
;
377 SmbiosRecord
-> CurrentSpeed
= *(UINT16
*) & Frequency
;
378 SmbiosRecord
-> MaxSpeed
= *(UINT16
*) & Frequency
;
381 // Processor Characteristics
383 AsmCpuid(0x8000000, NULL
, NULL
, NULL
, &Edx01
);
386 SmbiosRecord
-> ProcessorCharacteristics
= (UINT16
)Edx01
;
389 // Processor Core Count and Enabled core count
391 Status
= gBS
->LocateProtocol (
392 &gEfiMpServiceProtocolGuid
,
396 if (!EFI_ERROR (Status
)) {
398 // Determine the number of processors
400 MpService
->GetNumberOfProcessors (
403 &NumberOfEnabledProcessors
406 SmbiosRecord
-> CoreCount
= (UINT8
)NumberOfProcessors
;
407 SmbiosRecord
-> EnabledCoreCount
= (UINT8
)NumberOfEnabledProcessors
;
408 SmbiosRecord
-> ThreadCount
= (UINT8
)NumberOfEnabledProcessors
;
409 SmbiosRecord
-> ProcessorCharacteristics
= 0x2; // Unknown
412 // Processor Cache Handle
414 GetCacheHandle( Smbios
,1, &L1CacheHandle
);
415 GetCacheHandle( Smbios
,2, &L2CacheHandle
);
416 GetCacheHandle( Smbios
,3, &L3CacheHandle
);
419 // Updating Cache Handle Information
421 SmbiosRecord
->L1CacheHandle
= L1CacheHandle
;
422 SmbiosRecord
->L2CacheHandle
= L2CacheHandle
;
423 SmbiosRecord
->L3CacheHandle
= L3CacheHandle
;
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 );
434 // Now we have got the full Smbios record, call Smbios protocol to add this record.
436 SmbiosHandle
= SMBIOS_HANDLE_PI_RESERVED
;
437 Status
= Smbios
-> Add(
441 (EFI_SMBIOS_TABLE_HEADER
*) SmbiosRecord
443 if (EFI_ERROR (Status
)) return Status
;
444 FreePool(SmbiosRecord
);