]> git.proxmox.com Git - mirror_edk2.git/blobdiff - Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformationFunction.c
Upload BSD-licensed Vlv2TbltDevicePkg and Vlv2DeviceRefCodePkg to
[mirror_edk2.git] / Vlv2TbltDevicePkg / SmBiosMiscDxe / MiscProcessorInformationFunction.c
diff --git a/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformationFunction.c b/Vlv2TbltDevicePkg/SmBiosMiscDxe/MiscProcessorInformationFunction.c
new file mode 100644 (file)
index 0000000..005b43c
--- /dev/null
@@ -0,0 +1,455 @@
+/*++\r
+\r
+Copyright (c) 2006  - 2014, Intel Corporation. All rights reserved.<BR>\r
+                                                                                   \r\r
+  This program and the accompanying materials are licensed and made available under\r\r
+  the terms and conditions of the BSD License that accompanies this distribution.  \r\r
+  The full text of the license may be found at                                     \r\r
+  http://opensource.org/licenses/bsd-license.php.                                  \r\r
+                                                                                   \r\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,            \r\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.    \r\r
+                                                                                   \r\r
+\r
+\r
+Module Name:\r
+\r
+  MiscProcessorInformationFunction.c\r
+\r
+Abstract:\r
+\r
+  Onboard processor information boot time changes.\r
+  SMBIOS type 4.\r
+\r
+--*/\r
+\r
+#include "CommonHeader.h"\r
+\r
+#include "MiscSubclassDriver.h"\r
+\r
+#include <Protocol/MpService.h>\r
+#include <Protocol/DataHub.h>\r
+#include <Guid/DataHubRecords.h>\r
+#include <Library/CpuIA32.h>\r
+\r
+#define EfiProcessorFamilyIntelAtomProcessor    0x2B\r
+\r
+EFI_GUID                        mProcessorProducerGuid;\r
+\r
+\r
+/**\r
+  Get cache SMBIOS record handle.\r
+\r
+  @param  Smbios        Pointer to SMBIOS protocol instance.\r
+  @param  CacheLevel    Level of cache, starting from one.\r
+  @param  Handle        Returned record handle.\r
+\r
+**/\r
+\r
+VOID\r
+GetCacheHandle (\r
+  IN  EFI_SMBIOS_PROTOCOL      *Smbios,\r
+  IN  UINT8                    CacheLevel,\r
+  OUT  EFI_SMBIOS_HANDLE       *Handle\r
+  )\r
+{\r
+  UINT16                     CacheConfig;\r
+  EFI_STATUS                 Status;\r
+  EFI_SMBIOS_TYPE            RecordType;\r
+  EFI_SMBIOS_TABLE_HEADER    *Buffer;\r
+\r
+  *Handle = 0;\r
+  RecordType = EFI_SMBIOS_TYPE_CACHE_INFORMATION;\r
+\r
+  do {\r
+    Status = Smbios->GetNext (\r
+                       Smbios,\r
+                       Handle,\r
+                       &RecordType,\r
+                       &Buffer,\r
+                       NULL\r
+                       );\r
+    if (!EFI_ERROR(Status)) {\r
+      CacheConfig = *(UINT16*)((UINT8*)Buffer + 5);\r
+      if ((CacheConfig & 0x7) == (CacheLevel -1) ) {\r
+        return;\r
+      }\r
+    }\r
+  } while (!EFI_ERROR(Status));\r
+\r
+  *Handle = 0xFFFF;\r
+}\r
+\r
+\r
+/**\r
+  This function makes boot time changes to the contents of the\r
+  MiscProcessorInformation (Type 4).\r
+\r
+  @param  RecordData                 Pointer to copy of RecordData from the Data Table.\r
+\r
+  @retval EFI_SUCCESS                All parameters were valid.\r
+  @retval EFI_UNSUPPORTED            Unexpected RecordType value.\r
+  @retval EFI_INVALID_PARAMETER      Invalid parameter was found.\r
+\r
+**/\r
+UINT32\r
+ConvertBase10ToRaw (\r
+  IN  EFI_EXP_BASE10_DATA             *Data)\r
+{\r
+  UINTN         Index;\r
+  UINT32        RawData;\r
+\r
+  RawData = Data->Value;\r
+  for (Index = 0; Index < (UINTN) Data->Exponent; Index++) {\r
+     RawData *= 10;\r
+  }\r
+\r
+  return  RawData;\r
+}\r
+\r
+#define BSEL_CR_OVERCLOCK_CONTROL      0xCD\r
+#define        FUSE_BSEL_MASK                          0x03\r
+\r
+\r
+\r
+UINT16 miFSBFrequencyTable[4] = {\r
+  83,                  // 83.3MHz\r
+  100,          // 100MHz\r
+  133,          // 133MHz\r
+  117           // 116.7MHz\r
+};\r
+\r
+/**\r
+  Determine the processor core frequency\r
+\r
+  @param None\r
+\r
+  @retval Processor core frequency multiplied by 3\r
+\r
+\r
+**/\r
+UINT16\r
+DetermineiFsbFromMsr (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Determine the processor core frequency\r
+  //\r
+  UINT64       Temp;\r
+  Temp = (EfiReadMsr (BSEL_CR_OVERCLOCK_CONTROL)) & FUSE_BSEL_MASK;\r
+  return miFSBFrequencyTable[(UINT32)(Temp)];\r
+\r
+}\r
+\r
+MISC_SMBIOS_TABLE_FUNCTION (MiscProcessorInformation)\r
+{\r
+    CHAR8                           *OptionalStrStart;\r
+    EFI_STRING                      SerialNumber;\r
+    CHAR16                          *Version=NULL;\r
+    CHAR16                          *Manufacturer=NULL;\r
+    CHAR16                          *Socket=NULL;\r
+    CHAR16                          *AssetTag=NULL;\r
+    CHAR16                          *PartNumber=NULL;\r
+    UINTN                           SerialNumberStrLen=0;\r
+    UINTN                           VersionStrLen=0;\r
+    UINTN                           ManufacturerStrLen=0;\r
+    UINTN                           SocketStrLen=0;\r
+    UINTN                           AssetTagStrLen=0;\r
+    UINTN                           PartNumberStrLen=0;\r
+    UINTN                           ProcessorVoltage=0xAE;\r
+    UINT32                          Eax01;\r
+    UINT32                          Ebx01;\r
+    UINT32                          Ecx01;\r
+    UINT32                          Edx01;\r
+    STRING_REF                      TokenToGet;\r
+    EFI_STATUS                      Status;\r
+    EFI_SMBIOS_HANDLE               SmbiosHandle;\r
+    SMBIOS_TABLE_TYPE4              *SmbiosRecord;\r
+    EFI_CPU_DATA_RECORD             *ForType4InputData;\r
+    UINT16                          L1CacheHandle=0;\r
+    UINT16                          L2CacheHandle=0;\r
+    UINT16                          L3CacheHandle=0;\r
+    UINTN                           NumberOfEnabledProcessors=0 ;\r
+    UINTN                           NumberOfProcessors=0;\r
+    UINT64                          Frequency = 0;\r
+    EFI_MP_SERVICES_PROTOCOL        *MpService;\r
+    EFI_DATA_HUB_PROTOCOL           *DataHub;\r
+    UINT64                          MonotonicCount;\r
+    EFI_DATA_RECORD_HEADER          *Record;\r
+    EFI_SUBCLASS_TYPE1_HEADER       *DataHeader;\r
+    UINT8                           *SrcData;\r
+    UINT32                          SrcDataSize;\r
+    EFI_PROCESSOR_VERSION_DATA      *ProcessorVersion;\r
+    CHAR16                          *NewStringToken;\r
+    STRING_REF                      TokenToUpdate;\r
+    PROCESSOR_ID_DATA               *ProcessorId = NULL;\r
+\r
+\r
+    //\r
+    // First check for invalid parameters.\r
+    //\r
+    if (RecordData == NULL) {\r
+        return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    ForType4InputData = (EFI_CPU_DATA_RECORD *)RecordData;\r
+\r
+    ProcessorId = AllocateZeroPool(sizeof(PROCESSOR_ID_DATA));\r
+    if (ProcessorId == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    //\r
+    // Get the Data Hub Protocol. Assume only one instance\r
+    //\r
+    Status = gBS->LocateProtocol (\r
+                    &gEfiDataHubProtocolGuid,\r
+                    NULL,\r
+                    (VOID **)&DataHub\r
+                    );\r
+    ASSERT_EFI_ERROR(Status);\r
+\r
+    MonotonicCount = 0;\r
+    Record = NULL;\r
+\r
+    do {\r
+      Status = DataHub->GetNextRecord (\r
+                          DataHub,\r
+                          &MonotonicCount,\r
+                          NULL,\r
+                          &Record\r
+                          );\r
+       if (!EFI_ERROR(Status)) {\r
+         if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) {\r
+\r
+            DataHeader  = (EFI_SUBCLASS_TYPE1_HEADER *)(Record + 1);\r
+            SrcData     = (UINT8  *)(DataHeader + 1);\r
+            SrcDataSize = Record->RecordSize - Record->HeaderSize - sizeof (EFI_SUBCLASS_TYPE1_HEADER);\r
+\r
+            //\r
+            // Processor\r
+            //\r
+            if (CompareGuid(&Record->DataRecordGuid, &gEfiProcessorSubClassGuid)) {\r
+              CopyMem (&mProcessorProducerGuid, &Record->ProducerName, sizeof(EFI_GUID));\r
+              switch (DataHeader->RecordType) {\r
+                case ProcessorVoltageRecordType:\r
+                  ProcessorVoltage = (((EFI_EXP_BASE10_DATA *)SrcData)->Value)/100 + 0x80;\r
+                  break;\r
+                case ProcessorCoreFrequencyRecordType:\r
+                  DEBUG ((EFI_D_ERROR, "ProcessorCoreFrequencyRecordType SrcData1 =%d\n", ConvertBase10ToRaw((EFI_EXP_BASE10_DATA *)SrcData)/1000000));\r
+                  Frequency = (ConvertBase10ToRaw((EFI_EXP_BASE10_DATA *)SrcData)/1000000);\r
+                  break;\r
+                case ProcessorVersionRecordType:\r
+                  ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *)SrcData;\r
+                  NewStringToken = HiiGetPackageString(&mProcessorProducerGuid, *ProcessorVersion, NULL);\r
+                  TokenToUpdate = (STRING_REF)STR_MISC_PROCESSOR_VERSION;\r
+                  HiiSetString(mHiiHandle, TokenToUpdate, NewStringToken, NULL);\r
+                  break;\r
+                default:\r
+                  break;\r
+              }\r
+            }\r
+          }\r
+        }\r
+    } while (!EFI_ERROR(Status) && (MonotonicCount != 0));\r
+\r
+    //\r
+    // Token to get for Socket Name\r
+    //\r
+    TokenToGet = STRING_TOKEN (STR_MISC_SOCKET_NAME);\r
+    Socket = SmbiosMiscGetString (TokenToGet);\r
+    SocketStrLen = StrLen(Socket);\r
+    if (SocketStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
+         return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    //\r
+    // Token to get for Processor Manufacturer\r
+    //\r
+    TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_MAUFACTURER);\r
+    Manufacturer = SmbiosMiscGetString (TokenToGet);\r
+    ManufacturerStrLen = StrLen(Manufacturer);\r
+    if (ManufacturerStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    //\r
+    // Token to get for Processor Version\r
+    //\r
+    TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_VERSION);\r
+    Version = SmbiosMiscGetString (TokenToGet);\r
+    VersionStrLen = StrLen(Version);\r
+    if (VersionStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
+        return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    //\r
+    // Token to get for Serial Number\r
+    //\r
+    TokenToGet = STRING_TOKEN (STR_MISC_PROCESSOR_SERIAL_NUMBER);\r
+    SerialNumber = SmbiosMiscGetString (TokenToGet);\r
+    SerialNumberStrLen = StrLen(SerialNumber);\r
+    if (SerialNumberStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
+        return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    //\r
+    // Token to get for Assert Tag Information\r
+    //\r
+    TokenToGet = STRING_TOKEN (STR_MISC_ASSERT_TAG_DATA);\r
+    AssetTag = SmbiosMiscGetString (TokenToGet);\r
+    AssetTagStrLen = StrLen(AssetTag);\r
+    if (AssetTagStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
+        return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    //\r
+    // Token to get for part number Information\r
+    //\r
+    TokenToGet = STRING_TOKEN (STR_MISC_PART_NUMBER);\r
+    PartNumber = SmbiosMiscGetString (TokenToGet);\r
+    PartNumberStrLen = StrLen(PartNumber);\r
+    if (PartNumberStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
+         return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    //\r
+    // Two zeros following the last string.\r
+    //\r
+    SmbiosRecord = AllocateZeroPool(sizeof (SMBIOS_TABLE_TYPE4) + AssetTagStrLen + 1 + SocketStrLen + 1+ ManufacturerStrLen +1 + VersionStrLen+ 1+ SerialNumberStrLen + 1 + PartNumberStrLen+ 1 + 1);\r
+\r
+    SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;\r
+    SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE4);\r
+\r
+    //\r
+    // Make handle chosen by smbios protocol.add automatically.\r
+    //\r
+    SmbiosRecord->Hdr.Handle = 0;\r
+\r
+    SmbiosRecord-> Socket= 1;\r
+    SmbiosRecord -> ProcessorManufacture = 2;\r
+    SmbiosRecord -> ProcessorVersion = 3;\r
+    SmbiosRecord ->SerialNumber =4;\r
+\r
+    SmbiosRecord-> AssetTag= 5;\r
+    SmbiosRecord-> PartNumber= 6;\r
+\r
+    //\r
+    // Processor Type\r
+    //\r
+    ForType4InputData-> VariableRecord.ProcessorType= EfiCentralProcessor;\r
+    SmbiosRecord -> ProcessorType = ForType4InputData-> VariableRecord.ProcessorType;\r
+\r
+    //\r
+    // Processor Family\r
+    //\r
+    ForType4InputData-> VariableRecord.ProcessorFamily= EfiProcessorFamilyIntelAtomProcessor; //0x2B;;\r
+    SmbiosRecord -> ProcessorFamily = ForType4InputData-> VariableRecord.ProcessorFamily;\r
+    SmbiosRecord -> ExternalClock = DetermineiFsbFromMsr();\r
+\r
+    //\r
+    // Processor ID\r
+    //\r
+    AsmCpuid(0x001, &Eax01, &Ebx01, &Ecx01, &Edx01);\r
+    ProcessorId->Signature = *(PROCESSOR_SIGNATURE *)&Eax01;\r
+    ProcessorId->FeatureFlags = *(PROCESSOR_FEATURE_FLAGS *)&Edx01;\r
+    SmbiosRecord -> ProcessorId = *(PROCESSOR_ID_DATA *)ProcessorId;\r
+\r
+    //\r
+    // Processor Voltage\r
+    //\r
+    ForType4InputData-> VariableRecord.ProcessorVoltage= *(EFI_PROCESSOR_VOLTAGE_DATA *)&ProcessorVoltage;\r
+    SmbiosRecord -> Voltage = *(PROCESSOR_VOLTAGE *) &(ForType4InputData-> VariableRecord.ProcessorVoltage);\r
+\r
+    //\r
+    // Status\r
+    //\r
+    ForType4InputData-> VariableRecord.ProcessorHealthStatus= 0x41;//0x41;\r
+    SmbiosRecord -> Status = ForType4InputData-> VariableRecord.ProcessorHealthStatus;\r
+\r
+    //\r
+    // Processor Upgrade\r
+    //\r
+    SmbiosRecord -> ProcessorUpgrade = 0x008;\r
+\r
+    //\r
+    // Processor Family 2\r
+    //\r
+    SmbiosRecord -> ProcessorFamily2 = ForType4InputData-> VariableRecord.ProcessorFamily;\r
+\r
+    //\r
+    // Processor speed\r
+    //\r
+    SmbiosRecord-> CurrentSpeed = *(UINT16*) & Frequency;\r
+    SmbiosRecord-> MaxSpeed = *(UINT16*) & Frequency;\r
+\r
+    //\r
+    // Processor Characteristics\r
+    //\r
+    AsmCpuid(0x8000000, NULL, NULL, NULL, &Edx01);\r
+    Edx01= Edx01 >> 28;\r
+    Edx01 &= 0x01;\r
+    SmbiosRecord-> ProcessorCharacteristics= (UINT16)Edx01;\r
+\r
+    //\r
+    // Processor Core Count and Enabled core count\r
+    //\r
+    Status = gBS->LocateProtocol (\r
+                    &gEfiMpServiceProtocolGuid,\r
+                    NULL,\r
+                    (void **)&MpService\r
+                    );\r
+    if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Determine the number of processors\r
+    //\r
+    MpService->GetNumberOfProcessors (\r
+                 MpService,\r
+                 &NumberOfProcessors,\r
+                 &NumberOfEnabledProcessors\r
+                 );\r
+    }\r
+    SmbiosRecord-> CoreCount= (UINT8)NumberOfProcessors;\r
+    SmbiosRecord-> EnabledCoreCount= (UINT8)NumberOfEnabledProcessors;\r
+    SmbiosRecord-> ThreadCount= (UINT8)NumberOfEnabledProcessors;\r
+    SmbiosRecord-> ProcessorCharacteristics = 0x2; // Unknown\r
+\r
+    //\r
+    // Processor Cache Handle\r
+    //\r
+    GetCacheHandle( Smbios,1, &L1CacheHandle);\r
+    GetCacheHandle( Smbios,2, &L2CacheHandle);\r
+    GetCacheHandle( Smbios,3, &L3CacheHandle);\r
+\r
+    //\r
+    // Updating Cache Handle Information\r
+    //\r
+    SmbiosRecord->L1CacheHandle  = L1CacheHandle;\r
+    SmbiosRecord->L2CacheHandle  = L2CacheHandle;\r
+    SmbiosRecord->L3CacheHandle  = L3CacheHandle;\r
+\r
+    OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);\r
+    UnicodeStrToAsciiStr(Socket, OptionalStrStart);\r
+    UnicodeStrToAsciiStr(Manufacturer, OptionalStrStart + SocketStrLen + 1);\r
+    UnicodeStrToAsciiStr(Version, OptionalStrStart + SocketStrLen + 1 + ManufacturerStrLen+ 1);\r
+    UnicodeStrToAsciiStr(SerialNumber, OptionalStrStart + SocketStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1);\r
+    UnicodeStrToAsciiStr(AssetTag, OptionalStrStart + SerialNumberStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1 + SocketStrLen + 1);\r
+    UnicodeStrToAsciiStr(PartNumber, OptionalStrStart + SerialNumberStrLen + 1 + VersionStrLen + 1 + ManufacturerStrLen + 1 + SocketStrLen + 1 + AssetTagStrLen + 1 );\r
+\r
+    //\r
+    // Now we have got the full Smbios record, call Smbios protocol to add this record.\r
+    //\r
+    SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
+    Status = Smbios-> Add(\r
+                        Smbios,\r
+                        NULL,\r
+                        &SmbiosHandle,\r
+                        (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord\r
+                        );\r
+    if (EFI_ERROR (Status)) return Status;\r
+    FreePool(SmbiosRecord);\r
+    return Status;\r
+\r
+}\r
+\r