123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- /*++
- Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- Module Name:
- MiscProcessorInformationFunction.c
- Abstract:
- Onboard processor information boot time changes.
- SMBIOS type 4.
- --*/
- #include "CommonHeader.h"
- #include "MiscSubclassDriver.h"
- #include <Protocol/MpService.h>
- #include <Library/TimerLib.h>
- #include <Register/Cpuid.h>
- #define EfiProcessorFamilyIntelAtomProcessor 0x2B
- EFI_GUID mProcessorProducerGuid;
- /**
- Get cache SMBIOS record handle.
- @param Smbios Pointer to SMBIOS protocol instance.
- @param CacheLevel Level of cache, starting from one.
- @param Handle Returned record handle.
- **/
- VOID
- GetCacheHandle (
- IN EFI_SMBIOS_PROTOCOL *Smbios,
- IN UINT8 CacheLevel,
- OUT EFI_SMBIOS_HANDLE *Handle
- )
- {
- UINT16 CacheConfig;
- EFI_STATUS Status;
- EFI_SMBIOS_TYPE RecordType;
- EFI_SMBIOS_TABLE_HEADER *Buffer;
- *Handle = 0;
- RecordType = EFI_SMBIOS_TYPE_CACHE_INFORMATION;
- do {
- Status = Smbios->GetNext (
- Smbios,
- Handle,
- &RecordType,
- &Buffer,
- NULL
- );
- if (!EFI_ERROR(Status)) {
- CacheConfig = *(UINT16*)((UINT8*)Buffer + 5);
- if ((CacheConfig & 0x7) == (CacheLevel -1) ) {
- return;
- }
- }
- } while (!EFI_ERROR(Status));
- *Handle = 0xFFFF;
- }
- #define BSEL_CR_OVERCLOCK_CONTROL 0xCD
- #define FUSE_BSEL_MASK 0x03
- UINT16 miFSBFrequencyTable[4] = {
- 83, // 83.3MHz
- 100, // 100MHz
- 133, // 133MHz
- 117 // 116.7MHz
- };
- /**
- Determine the processor core frequency
- @param None
- @retval Processor core frequency multiplied by 3
- **/
- UINT16
- DetermineiFsbFromMsr (
- VOID
- )
- {
- //
- // Determine the processor core frequency
- //
- UINT64 Temp;
- Temp = (AsmReadMsr64 (BSEL_CR_OVERCLOCK_CONTROL)) & FUSE_BSEL_MASK;
- return miFSBFrequencyTable[(UINT32)(Temp)];
- }
- CHAR16 *
- CpuidSocVendorBrandString (
- VOID
- )
- {
- UINT32 MaximumExtendedFunction;
- //
- // Array to store brand string from 3 brand string leafs with
- // 4 32-bit brand string values per leaf and an extra value to
- // null terminate the string.
- //
- UINT32 BrandString[3 * 4 + 1];
- CHAR8 *AsciiBrandString;
- CHAR16 *UnicodeBrandString;
- UINTN Length;
- AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaximumExtendedFunction, NULL, NULL, NULL);
- ZeroMem (&BrandString, sizeof (BrandString));
- if (CPUID_BRAND_STRING1 <= MaximumExtendedFunction) {
- AsmCpuid (
- CPUID_BRAND_STRING1,
- &BrandString[0],
- &BrandString[1],
- &BrandString[2],
- &BrandString[3]
- );
- }
- if (CPUID_BRAND_STRING2 <= MaximumExtendedFunction) {
- AsmCpuid (
- CPUID_BRAND_STRING2,
- &BrandString[4],
- &BrandString[5],
- &BrandString[6],
- &BrandString[7]
- );
- }
- if (CPUID_BRAND_STRING3 <= MaximumExtendedFunction) {
- AsmCpuid (
- CPUID_BRAND_STRING3,
- &BrandString[8],
- &BrandString[9],
- &BrandString[10],
- &BrandString[11]
- );
- }
- //
- // Skip spaces at the beginning of the brand string
- //
- for (AsciiBrandString = (CHAR8 *)BrandString; *AsciiBrandString == ' '; AsciiBrandString++);
- DEBUG ((DEBUG_INFO, "Processor Brand String = %a\n", AsciiBrandString));
- //
- // Convert ASCII brand string to an allocated Unicode brand string
- //
- Length = AsciiStrLen (AsciiBrandString) + 1;
- UnicodeBrandString = AllocatePool (Length * sizeof (CHAR16));
- AsciiStrToUnicodeStrS (AsciiBrandString, UnicodeBrandString, Length);
- DEBUG ((DEBUG_INFO, "Processor Unicode Brand String = %s\n", UnicodeBrandString));
- return UnicodeBrandString;
- }
- UINT64
- MeasureTscFrequency (
- VOID
- )
- {
- EFI_TPL CurrentTpl;
- UINT64 BeginValue;
- UINT64 EndValue;
- UINT64 Frequency;
- //
- // Wait for 10000us = 10ms for the calculation
- // It needs a precise timer to calculate the ticks
- //
- CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
- BeginValue = AsmReadTsc ();
- MicroSecondDelay (10000);
- EndValue = AsmReadTsc ();
- gBS->RestoreTPL (CurrentTpl);
- Frequency = MultU64x32 (EndValue - BeginValue, 1000);
- Frequency = DivU64x32 (Frequency, 10);
- return Frequency;
- }
- MISC_SMBIOS_TABLE_FUNCTION (MiscProcessorInformation)
- {
- CHAR8 *OptionalStrStart;
- UINTN OptionalStrSize;
- EFI_STRING SerialNumber;
- CHAR16 *Version=NULL;
- CHAR16 *Manufacturer=NULL;
- CHAR16 *Socket=NULL;
- CHAR16 *AssetTag=NULL;
- CHAR16 *PartNumber=NULL;
- UINTN SerialNumberStrLen=0;
- UINTN VersionStrLen=0;
- UINTN ManufacturerStrLen=0;
- UINTN SocketStrLen=0;
- UINTN AssetTagStrLen=0;
- UINTN PartNumberStrLen=0;
- UINTN ProcessorVoltage=(BIT7 | 9);
- UINT32 Eax01;
- UINT32 Ebx01;
- UINT32 Ecx01;
- UINT32 Edx01;
- STRING_REF TokenToGet;
- EFI_STATUS Status;
- EFI_SMBIOS_HANDLE SmbiosHandle;
- SMBIOS_TABLE_TYPE4 *SmbiosRecord;
- EFI_CPU_DATA_RECORD *ForType4InputData;
- UINT16 L1CacheHandle=0;
- UINT16 L2CacheHandle=0;
- UINT16 L3CacheHandle=0;
- UINTN NumberOfEnabledProcessors=0 ;
- UINTN NumberOfProcessors=0;
- UINT64 Frequency = 0;
- EFI_MP_SERVICES_PROTOCOL *MpService;
- PROCESSOR_ID_DATA *ProcessorId = NULL;
- //
- // First check for invalid parameters.
- //
- if (RecordData == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- ForType4InputData = (EFI_CPU_DATA_RECORD *)RecordData;
- ProcessorId = AllocateZeroPool(sizeof(PROCESSOR_ID_DATA));
- if (ProcessorId == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Token to get for Socket Name
- //
- TokenToGet = STRING_TOKEN (STR_MISC_SOCKET_NAME);
- Socket = SmbiosMiscGetString (TokenToGet);
- SocketStrLen = StrLen(Socket);
- if (SocketStrLen > SMBIOS_STRING_MAX_LENGTH) {
- return EFI_UNSUPPORTED;
- }
- //
- // Token to get for Processor Manufacturer
- //
- TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_MAUFACTURER);
- Manufacturer = SmbiosMiscGetString (TokenToGet);
- ManufacturerStrLen = StrLen(Manufacturer);
- if (ManufacturerStrLen > SMBIOS_STRING_MAX_LENGTH) {
- return EFI_UNSUPPORTED;
- }
- //
- // Token to get for Processor Version
- //
- Version = CpuidSocVendorBrandString ();
- VersionStrLen = StrLen(Version);
- if (VersionStrLen > SMBIOS_STRING_MAX_LENGTH) {
- return EFI_UNSUPPORTED;
- }
- //
- // Token to get for Serial Number
- //
- TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_SERIAL_NUMBER);
- SerialNumber = SmbiosMiscGetString (TokenToGet);
- SerialNumberStrLen = StrLen(SerialNumber);
- if (SerialNumberStrLen > SMBIOS_STRING_MAX_LENGTH) {
- return EFI_UNSUPPORTED;
- }
- //
- // Token to get for Assert Tag Information
- //
- TokenToGet = STRING_TOKEN (STR_MISC_ASSERT_TAG_DATA);
- AssetTag = SmbiosMiscGetString (TokenToGet);
- AssetTagStrLen = StrLen(AssetTag);
- if (AssetTagStrLen > SMBIOS_STRING_MAX_LENGTH) {
- return EFI_UNSUPPORTED;
- }
- //
- // Token to get for part number Information
- //
- TokenToGet = STRING_TOKEN (STR_MISC_PART_NUMBER);
- PartNumber = SmbiosMiscGetString (TokenToGet);
- PartNumberStrLen = StrLen(PartNumber);
- if (PartNumberStrLen > SMBIOS_STRING_MAX_LENGTH) {
- return EFI_UNSUPPORTED;
- }
- //
- // Two zeros following the last string.
- //
- OptionalStrSize = AssetTagStrLen + 1 + SocketStrLen + 1+ ManufacturerStrLen +1 + VersionStrLen+ 1+ SerialNumberStrLen + 1 + PartNumberStrLen+ 1 + 1;
- SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE4) + OptionalStrSize);
- SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;
- SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE4);
- //
- // Make handle chosen by smbios protocol.add automatically.
- //
- SmbiosRecord->Hdr.Handle = 0;
- SmbiosRecord-> Socket= 1;
- SmbiosRecord -> ProcessorManufacturer = 2;
- SmbiosRecord -> ProcessorVersion = 3;
- SmbiosRecord ->SerialNumber =4;
- SmbiosRecord-> AssetTag= 5;
- SmbiosRecord-> PartNumber= 6;
- //
- // Processor Type
- //
- ForType4InputData-> VariableRecord.ProcessorType= EfiCentralProcessor;
- SmbiosRecord -> ProcessorType = ForType4InputData-> VariableRecord.ProcessorType;
- //
- // Processor Family
- //
- ForType4InputData-> VariableRecord.ProcessorFamily= EfiProcessorFamilyIntelAtomProcessor; //0x2B;;
- SmbiosRecord -> ProcessorFamily = ForType4InputData-> VariableRecord.ProcessorFamily;
- SmbiosRecord -> ExternalClock = DetermineiFsbFromMsr();
- //
- // Processor ID
- //
- AsmCpuid(0x001, &Eax01, &Ebx01, &Ecx01, &Edx01);
- ProcessorId->Signature = *(PROCESSOR_SIGNATURE *)&Eax01;
- ProcessorId->FeatureFlags = *(PROCESSOR_FEATURE_FLAGS *)&Edx01;
- SmbiosRecord -> ProcessorId = *(PROCESSOR_ID_DATA *)ProcessorId;
- //
- // Processor Voltage
- //
- ForType4InputData-> VariableRecord.ProcessorVoltage= *(EFI_PROCESSOR_VOLTAGE_DATA *)&ProcessorVoltage;
- SmbiosRecord -> Voltage = *(PROCESSOR_VOLTAGE *) &(ForType4InputData-> VariableRecord.ProcessorVoltage);
- //
- // Status
- //
- ForType4InputData-> VariableRecord.ProcessorHealthStatus= 0x41;//0x41;
- SmbiosRecord -> Status = ForType4InputData-> VariableRecord.ProcessorHealthStatus;
- //
- // Processor Upgrade
- //
- SmbiosRecord -> ProcessorUpgrade = 0x008;
- //
- // Processor Family 2
- //
- SmbiosRecord -> ProcessorFamily2 = ForType4InputData-> VariableRecord.ProcessorFamily;
- //
- // Processor speed in MHz
- //
- Frequency = MeasureTscFrequency ();
- Frequency = DivU64x32 (Frequency, 1000000);
- SmbiosRecord-> CurrentSpeed = (UINT16)Frequency;
- SmbiosRecord-> MaxSpeed = (UINT16)Frequency;
- //
- // Processor Characteristics
- //
- AsmCpuid(0x8000000, NULL, NULL, NULL, &Edx01);
- Edx01= Edx01 >> 28;
- Edx01 &= 0x01;
- SmbiosRecord-> ProcessorCharacteristics= (UINT16)Edx01;
- //
- // Processor Core Count and Enabled core count
- //
- Status = gBS->LocateProtocol (
- &gEfiMpServiceProtocolGuid,
- NULL,
- (void **)&MpService
- );
- if (!EFI_ERROR (Status)) {
- //
- // Determine the number of processors
- //
- MpService->GetNumberOfProcessors (
- MpService,
- &NumberOfProcessors,
- &NumberOfEnabledProcessors
- );
- }
- SmbiosRecord-> CoreCount= (UINT8)NumberOfProcessors;
- SmbiosRecord-> EnabledCoreCount= (UINT8)NumberOfEnabledProcessors;
- SmbiosRecord-> ThreadCount= (UINT8)NumberOfEnabledProcessors;
- SmbiosRecord-> ProcessorCharacteristics = 0x2; // Unknown
- //
- // Processor Cache Handle
- //
- GetCacheHandle( Smbios,1, &L1CacheHandle);
- GetCacheHandle( Smbios,2, &L2CacheHandle);
- GetCacheHandle( Smbios,3, &L3CacheHandle);
- //
- // Updating Cache Handle Information
- //
- SmbiosRecord->L1CacheHandle = L1CacheHandle;
- SmbiosRecord->L2CacheHandle = L2CacheHandle;
- SmbiosRecord->L3CacheHandle = L3CacheHandle;
- OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
- UnicodeStrToAsciiStrS (Socket, OptionalStrStart, OptionalStrSize);
- OptionalStrStart += (SocketStrLen + 1);
- OptionalStrSize -= (SocketStrLen + 1);
- UnicodeStrToAsciiStrS (Manufacturer, OptionalStrStart, OptionalStrSize);
- OptionalStrStart += (ManufacturerStrLen + 1);
- OptionalStrSize -= (ManufacturerStrLen + 1);
- UnicodeStrToAsciiStrS (Version, OptionalStrStart, OptionalStrSize);
- OptionalStrStart += (VersionStrLen + 1);
- OptionalStrSize -= (VersionStrLen + 1);
- UnicodeStrToAsciiStrS (SerialNumber, OptionalStrStart, OptionalStrSize);
- OptionalStrStart += (SerialNumberStrLen + 1);
- OptionalStrSize -= (SerialNumberStrLen + 1);
- UnicodeStrToAsciiStrS (AssetTag, OptionalStrStart, OptionalStrSize);
- OptionalStrStart += (AssetTagStrLen + 1);
- OptionalStrSize -= (AssetTagStrLen + 1);
- UnicodeStrToAsciiStrS (PartNumber, OptionalStrStart, OptionalStrSize);
- //
- // Now we have got the full Smbios record, call Smbios protocol to add this record.
- //
- SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
- Status = Smbios-> Add(
- Smbios,
- NULL,
- &SmbiosHandle,
- (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
- );
- if (EFI_ERROR (Status)) return Status;
- FreePool(SmbiosRecord);
- return Status;
- }
|