X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=Vlv2TbltDevicePkg%2FSmBiosMiscDxe%2FMiscProcessorInformationFunction.c;fp=Vlv2TbltDevicePkg%2FSmBiosMiscDxe%2FMiscProcessorInformationFunction.c;h=005b43cde501e58439bed30d42b0e3245c3f549f;hb=3cbfba02fef9dae07a041fdbf2e89611d72d6f90;hp=0000000000000000000000000000000000000000;hpb=6f785cfcc304c48ec04e542ee429df95e7b51bc5;p=mirror_edk2.git diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformationFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformationFunction.c new file mode 100644 index 0000000000..005b43cde5 --- /dev/null +++ b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformationFunction.c @@ -0,0 +1,455 @@ +/*++ + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made available under + the terms and conditions of the BSD License that accompanies this distribution. + The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + +Module Name: + + MiscProcessorInformationFunction.c + +Abstract: + + Onboard processor information boot time changes. + SMBIOS type 4. + +--*/ + +#include "CommonHeader.h" + +#include "MiscSubclassDriver.h" + +#include +#include +#include +#include + +#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; +} + + +/** + This function makes boot time changes to the contents of the + MiscProcessorInformation (Type 4). + + @param RecordData Pointer to copy of RecordData from the Data Table. + + @retval EFI_SUCCESS All parameters were valid. + @retval EFI_UNSUPPORTED Unexpected RecordType value. + @retval EFI_INVALID_PARAMETER Invalid parameter was found. + +**/ +UINT32 +ConvertBase10ToRaw ( + IN EFI_EXP_BASE10_DATA *Data) +{ + UINTN Index; + UINT32 RawData; + + RawData = Data->Value; + for (Index = 0; Index < (UINTN) Data->Exponent; Index++) { + RawData *= 10; + } + + return RawData; +} + +#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 = (EfiReadMsr (BSEL_CR_OVERCLOCK_CONTROL)) & FUSE_BSEL_MASK; + return miFSBFrequencyTable[(UINT32)(Temp)]; + +} + +MISC_SMBIOS_TABLE_FUNCTION (MiscProcessorInformation) +{ + CHAR8 *OptionalStrStart; + 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=0xAE; + 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; + EFI_DATA_HUB_PROTOCOL *DataHub; + UINT64 MonotonicCount; + EFI_DATA_RECORD_HEADER *Record; + EFI_SUBCLASS_TYPE1_HEADER *DataHeader; + UINT8 *SrcData; + UINT32 SrcDataSize; + EFI_PROCESSOR_VERSION_DATA *ProcessorVersion; + CHAR16 *NewStringToken; + STRING_REF TokenToUpdate; + 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; + } + + // + // Get the Data Hub Protocol. Assume only one instance + // + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + (VOID **)&DataHub + ); + ASSERT_EFI_ERROR(Status); + + MonotonicCount = 0; + Record = NULL; + + do { + Status = DataHub->GetNextRecord ( + DataHub, + &MonotonicCount, + NULL, + &Record + ); + if (!EFI_ERROR(Status)) { + if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) { + + DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *)(Record + 1); + SrcData = (UINT8 *)(DataHeader + 1); + SrcDataSize = Record->RecordSize - Record->HeaderSize - sizeof (EFI_SUBCLASS_TYPE1_HEADER); + + // + // Processor + // + if (CompareGuid(&Record->DataRecordGuid, &gEfiProcessorSubClassGuid)) { + CopyMem (&mProcessorProducerGuid, &Record->ProducerName, sizeof(EFI_GUID)); + switch (DataHeader->RecordType) { + case ProcessorVoltageRecordType: + ProcessorVoltage = (((EFI_EXP_BASE10_DATA *)SrcData)->Value)/100 + 0x80; + break; + case ProcessorCoreFrequencyRecordType: + DEBUG ((EFI_D_ERROR, "ProcessorCoreFrequencyRecordType SrcData1 =%d\n", ConvertBase10ToRaw((EFI_EXP_BASE10_DATA *)SrcData)/1000000)); + Frequency = (ConvertBase10ToRaw((EFI_EXP_BASE10_DATA *)SrcData)/1000000); + break; + case ProcessorVersionRecordType: + ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *)SrcData; + NewStringToken = HiiGetPackageString(&mProcessorProducerGuid, *ProcessorVersion, NULL); + TokenToUpdate = (STRING_REF)STR_MISC_PROCESSOR_VERSION; + HiiSetString(mHiiHandle, TokenToUpdate, NewStringToken, NULL); + break; + default: + break; + } + } + } + } + } while (!EFI_ERROR(Status) && (MonotonicCount != 0)); + + // + // 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 + // + TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_VERSION); + Version = SmbiosMiscGetString (TokenToGet); + 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. + // + SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE4) + AssetTagStrLen + 1 + SocketStrLen + 1+ ManufacturerStrLen +1 + VersionStrLen+ 1+ SerialNumberStrLen + 1 + PartNumberStrLen+ 1 + 1); + + 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 -> ProcessorManufacture = 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 + // + 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); + UnicodeStrToAsciiStr(Socket, OptionalStrStart); + UnicodeStrToAsciiStr(Manufacturer, OptionalStrStart + SocketStrLen + 1); + UnicodeStrToAsciiStr(Version, OptionalStrStart + SocketStrLen + 1 + ManufacturerStrLen+ 1); + UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + SocketStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1); + UnicodeStrToAsciiStr(AssetTag, OptionalStrStart + SerialNumberStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1 + SocketStrLen + 1); + UnicodeStrToAsciiStr(PartNumber, OptionalStrStart + SerialNumberStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1 + SocketStrLen + 1 + AssetTagStrLen + 1 ); + + // + // 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; + +} +