mirror of https://github.com/acidanthera/audk.git
753 lines
24 KiB
C
753 lines
24 KiB
C
/** @file
|
|
ProcessorSubClass.c
|
|
|
|
Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
|
|
Copyright (c) 2015, Hisilicon Limited. All rights reserved.
|
|
Copyright (c) 2015, Linaro Limited. All rights reserved.
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include <Uefi.h>
|
|
#include <Protocol/Smbios.h>
|
|
#include <IndustryStandard/ArmStdSmc.h>
|
|
#include <IndustryStandard/SmBios.h>
|
|
#include <Library/ArmLib.h>
|
|
#include <Library/ArmSmcLib.h>
|
|
#include <Library/ArmLib/ArmLibPrivate.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/HiiLib.h>
|
|
#include <Library/IoLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/OemMiscLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Library/PrintLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiLib.h>
|
|
|
|
#include "SmbiosProcessor.h"
|
|
|
|
extern UINT8 ProcessorSubClassStrings[];
|
|
|
|
#define CACHE_SOCKETED_SHIFT 3
|
|
#define CACHE_LOCATION_SHIFT 5
|
|
#define CACHE_ENABLED_SHIFT 7
|
|
#define CACHE_OPERATION_MODE_SHIFT 8
|
|
|
|
typedef enum {
|
|
CacheModeWriteThrough = 0, ///< Cache is write-through
|
|
CacheModeWriteBack, ///< Cache is write-back
|
|
CacheModeVariesWithAddress, ///< Cache mode varies by address
|
|
CacheModeUnknown, ///< Cache mode is unknown
|
|
CacheModeMax
|
|
} CACHE_OPERATION_MODE;
|
|
|
|
typedef enum {
|
|
CacheLocationInternal = 0, ///< Cache is internal to the processor
|
|
CacheLocationExternal, ///< Cache is external to the processor
|
|
CacheLocationReserved, ///< Reserved
|
|
CacheLocationUnknown, ///< Cache location is unknown
|
|
CacheLocationMax
|
|
} CACHE_LOCATION;
|
|
|
|
EFI_HII_HANDLE mHiiHandle;
|
|
|
|
EFI_SMBIOS_PROTOCOL *mSmbios;
|
|
|
|
SMBIOS_TABLE_TYPE4 mSmbiosProcessorTableTemplate = {
|
|
{ // Hdr
|
|
EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION, // Type
|
|
sizeof (SMBIOS_TABLE_TYPE4), // Length
|
|
0 // Handle
|
|
},
|
|
1, // Socket
|
|
CentralProcessor, // ProcessorType
|
|
ProcessorFamilyIndicatorFamily2, // ProcessorFamily
|
|
2, // ProcessorManufacture
|
|
{ // ProcessorId
|
|
{ // Signature
|
|
0
|
|
},
|
|
{ // FeatureFlags
|
|
0
|
|
}
|
|
},
|
|
3, // ProcessorVersion
|
|
{ // Voltage
|
|
0
|
|
},
|
|
0, // ExternalClock
|
|
0, // MaxSpeed
|
|
0, // CurrentSpeed
|
|
0, // Status
|
|
ProcessorUpgradeUnknown, // ProcessorUpgrade
|
|
0xFFFF, // L1CacheHandle
|
|
0xFFFF, // L2CacheHandle
|
|
0xFFFF, // L3CacheHandle
|
|
4, // SerialNumber
|
|
5, // AssetTag
|
|
6, // PartNumber
|
|
0, // CoreCount
|
|
0, //EnabledCoreCount
|
|
0, // ThreadCount
|
|
0, // ProcessorCharacteristics
|
|
ProcessorFamilyARM, // ProcessorFamily2
|
|
0, // CoreCount2
|
|
0, // EnabledCoreCount2
|
|
0 // ThreadCount2
|
|
};
|
|
|
|
/** Sets the HII variable `StringId` is `Pcd` isn't empty.
|
|
|
|
@param Pcd The FixedAtBuild PCD that contains the string to fetch.
|
|
@param StringId The string identifier to set.
|
|
**/
|
|
#define SET_HII_STRING_IF_PCD_NOT_EMPTY(Pcd, StringId) \
|
|
do { \
|
|
CHAR16 *Str; \
|
|
Str = (CHAR16*)PcdGetPtr (Pcd); \
|
|
if (StrLen (Str) > 0) { \
|
|
HiiSetString (mHiiHandle, StringId, Str, NULL); \
|
|
} \
|
|
} while (0)
|
|
|
|
/** Fetches the specified processor's frequency in Hz.
|
|
|
|
@param ProcessorNumber The processor number
|
|
|
|
@return The clock frequency in MHz
|
|
|
|
**/
|
|
UINT16
|
|
GetCpuFrequency (
|
|
IN UINT8 ProcessorNumber
|
|
)
|
|
{
|
|
return (UINT16)(OemGetCpuFreq (ProcessorNumber) / 1000 / 1000);
|
|
}
|
|
|
|
/** Gets a description of the specified cache.
|
|
|
|
@param[in] CacheLevel Zero-based cache level (e.g. L1 cache is 0).
|
|
@param[in] DataCache Cache is a data cache.
|
|
@param[in] UnifiedCache Cache is a unified cache.
|
|
@param[out] CacheSocketStr The description of the specified cache
|
|
|
|
@return The number of Unicode characters in CacheSocketStr not including the
|
|
terminating NUL.
|
|
**/
|
|
UINTN
|
|
GetCacheSocketStr (
|
|
IN UINT8 CacheLevel,
|
|
IN BOOLEAN DataCache,
|
|
IN BOOLEAN UnifiedCache,
|
|
OUT CHAR16 *CacheSocketStr
|
|
)
|
|
{
|
|
UINTN CacheSocketStrLen;
|
|
|
|
if (CacheLevel == CpuCacheL1 && !DataCache && !UnifiedCache) {
|
|
CacheSocketStrLen = UnicodeSPrint (
|
|
CacheSocketStr,
|
|
SMBIOS_STRING_MAX_LENGTH - 1,
|
|
L"L%x Instruction Cache",
|
|
CacheLevel);
|
|
} else if (CacheLevel == CpuCacheL1 && DataCache) {
|
|
CacheSocketStrLen = UnicodeSPrint (CacheSocketStr,
|
|
SMBIOS_STRING_MAX_LENGTH - 1,
|
|
L"L%x Data Cache",
|
|
CacheLevel);
|
|
} else {
|
|
CacheSocketStrLen = UnicodeSPrint (CacheSocketStr,
|
|
SMBIOS_STRING_MAX_LENGTH - 1,
|
|
L"L%x Cache",
|
|
CacheLevel);
|
|
}
|
|
|
|
return CacheSocketStrLen;
|
|
}
|
|
|
|
/** Fills in the Type 7 record with the cache architecture information
|
|
read from the CPU registers.
|
|
|
|
@param[in] CacheLevel Cache level (e.g. L1, L2).
|
|
@param[in] DataCache Cache is a data cache.
|
|
@param[in] UnifiedCache Cache is a unified cache.
|
|
@param[out] Type7Record The Type 7 record to fill in.
|
|
|
|
**/
|
|
VOID
|
|
ConfigureCacheArchitectureInformation (
|
|
IN UINT8 CacheLevel,
|
|
IN BOOLEAN DataCache,
|
|
IN BOOLEAN UnifiedCache,
|
|
OUT SMBIOS_TABLE_TYPE7 *Type7Record
|
|
)
|
|
{
|
|
UINT8 Associativity;
|
|
UINT32 CacheSize32;
|
|
UINT16 CacheSize16;
|
|
UINT64 CacheSize64;
|
|
|
|
if (!DataCache && !UnifiedCache) {
|
|
Type7Record->SystemCacheType = CacheTypeInstruction;
|
|
} else if (DataCache) {
|
|
Type7Record->SystemCacheType = CacheTypeData;
|
|
} else if (UnifiedCache) {
|
|
Type7Record->SystemCacheType = CacheTypeUnified;
|
|
} else {
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
CacheSize64 = SmbiosProcessorGetCacheSize (CacheLevel,
|
|
DataCache,
|
|
UnifiedCache
|
|
);
|
|
|
|
Associativity = SmbiosProcessorGetCacheAssociativity (CacheLevel,
|
|
DataCache,
|
|
UnifiedCache
|
|
);
|
|
|
|
CacheSize64 /= 1024; // Minimum granularity is 1K
|
|
|
|
// Encode the cache size into the format SMBIOS wants
|
|
if (CacheSize64 < MAX_INT16) {
|
|
CacheSize16 = CacheSize64;
|
|
CacheSize32 = CacheSize16;
|
|
} else if ((CacheSize64 / 64) < MAX_INT16) {
|
|
CacheSize16 = (1 << 15) | (CacheSize64 / 64);
|
|
CacheSize32 = CacheSize16;
|
|
} else {
|
|
if ((CacheSize64 / 1024) <= 2047) {
|
|
CacheSize32 = CacheSize64;
|
|
} else {
|
|
CacheSize32 = (1 << 31) | (CacheSize64 / 64);
|
|
}
|
|
|
|
CacheSize16 = -1;
|
|
}
|
|
|
|
Type7Record->MaximumCacheSize = CacheSize16;
|
|
Type7Record->InstalledSize = CacheSize16;
|
|
Type7Record->MaximumCacheSize2 = CacheSize32;
|
|
Type7Record->InstalledSize2 = CacheSize32;
|
|
|
|
switch (Associativity) {
|
|
case 2:
|
|
Type7Record->Associativity = CacheAssociativity2Way;
|
|
break;
|
|
case 4:
|
|
Type7Record->Associativity = CacheAssociativity4Way;
|
|
break;
|
|
case 8:
|
|
Type7Record->Associativity = CacheAssociativity8Way;
|
|
break;
|
|
case 12:
|
|
Type7Record->Associativity = CacheAssociativity12Way;
|
|
break;
|
|
case 16:
|
|
Type7Record->Associativity = CacheAssociativity16Way;
|
|
break;
|
|
case 20:
|
|
Type7Record->Associativity = CacheAssociativity20Way;
|
|
break;
|
|
case 24:
|
|
Type7Record->Associativity = CacheAssociativity24Way;
|
|
break;
|
|
case 32:
|
|
Type7Record->Associativity = CacheAssociativity32Way;
|
|
break;
|
|
case 48:
|
|
Type7Record->Associativity = CacheAssociativity48Way;
|
|
break;
|
|
case 64:
|
|
Type7Record->Associativity = CacheAssociativity64Way;
|
|
break;
|
|
default:
|
|
Type7Record->Associativity = CacheAssociativityOther;
|
|
break;
|
|
}
|
|
|
|
Type7Record->CacheConfiguration = (CacheModeUnknown << CACHE_OPERATION_MODE_SHIFT) |
|
|
(1 << CACHE_ENABLED_SHIFT) |
|
|
(CacheLocationUnknown << CACHE_LOCATION_SHIFT) |
|
|
(0 << CACHE_SOCKETED_SHIFT) |
|
|
(CacheLevel - 1);
|
|
}
|
|
|
|
|
|
/** Allocates and initializes an SMBIOS_TABLE_TYPE7 structure.
|
|
|
|
@param[in] CacheLevel The cache level (L1-L7).
|
|
@param[in] DataCache Cache is a data cache.
|
|
@param[in] UnifiedCache Cache is a unified cache.
|
|
|
|
@return A pointer to the Type 7 structure. Returns NULL on failure.
|
|
**/
|
|
SMBIOS_TABLE_TYPE7 *
|
|
AllocateAndInitCacheInformation (
|
|
IN UINT8 CacheLevel,
|
|
IN BOOLEAN DataCache,
|
|
IN BOOLEAN UnifiedCache
|
|
)
|
|
{
|
|
SMBIOS_TABLE_TYPE7 *Type7Record;
|
|
EFI_STRING CacheSocketStr;
|
|
UINTN CacheSocketStrLen;
|
|
UINTN StringBufferSize;
|
|
CHAR8 *OptionalStrStart;
|
|
UINTN TableSize;
|
|
|
|
// Allocate and fetch the cache description
|
|
StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;
|
|
CacheSocketStr = AllocateZeroPool (StringBufferSize);
|
|
if (CacheSocketStr == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
CacheSocketStrLen = GetCacheSocketStr (CacheLevel,
|
|
DataCache,
|
|
UnifiedCache,
|
|
CacheSocketStr);
|
|
|
|
TableSize = sizeof (SMBIOS_TABLE_TYPE7) + CacheSocketStrLen + 1 + 1;
|
|
Type7Record = AllocateZeroPool (TableSize);
|
|
if (Type7Record == NULL) {
|
|
FreePool(CacheSocketStr);
|
|
return NULL;
|
|
}
|
|
|
|
Type7Record->Hdr.Type = EFI_SMBIOS_TYPE_CACHE_INFORMATION;
|
|
Type7Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE7);
|
|
Type7Record->Hdr.Handle = SMBIOS_HANDLE_PI_RESERVED;
|
|
|
|
Type7Record->SocketDesignation = 1;
|
|
|
|
Type7Record->SupportedSRAMType.Unknown = 1;
|
|
Type7Record->CurrentSRAMType.Unknown = 1;
|
|
Type7Record->CacheSpeed = 0;
|
|
Type7Record->ErrorCorrectionType = CacheErrorUnknown;
|
|
|
|
OptionalStrStart = (CHAR8 *)(Type7Record + 1);
|
|
UnicodeStrToAsciiStrS (CacheSocketStr, OptionalStrStart, CacheSocketStrLen + 1);
|
|
FreePool (CacheSocketStr);
|
|
|
|
return Type7Record;
|
|
}
|
|
|
|
/**
|
|
Add Type 7 SMBIOS Record for Cache Information.
|
|
|
|
@param[in] ProcessorIndex Processor number of specified processor.
|
|
@param[out] L1CacheHandle Pointer to the handle of the L1 Cache SMBIOS record.
|
|
@param[out] L2CacheHandle Pointer to the handle of the L2 Cache SMBIOS record.
|
|
@param[out] L3CacheHandle Pointer to the handle of the L3 Cache SMBIOS record.
|
|
|
|
**/
|
|
VOID
|
|
AddSmbiosCacheTypeTable (
|
|
IN UINTN ProcessorIndex,
|
|
OUT EFI_SMBIOS_HANDLE *L1CacheHandle,
|
|
OUT EFI_SMBIOS_HANDLE *L2CacheHandle,
|
|
OUT EFI_SMBIOS_HANDLE *L3CacheHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
SMBIOS_TABLE_TYPE7 *Type7Record;
|
|
EFI_SMBIOS_HANDLE SmbiosHandle;
|
|
UINT8 CacheLevel;
|
|
UINT8 MaxCacheLevel;
|
|
BOOLEAN DataCacheType;
|
|
BOOLEAN SeparateCaches;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
MaxCacheLevel = 0;
|
|
|
|
// See if there's an L1 cache present.
|
|
MaxCacheLevel = SmbiosProcessorGetMaxCacheLevel ();
|
|
|
|
if (MaxCacheLevel < 1) {
|
|
return;
|
|
}
|
|
|
|
for (CacheLevel = 1; CacheLevel <= MaxCacheLevel; CacheLevel++) {
|
|
Type7Record = NULL;
|
|
|
|
SeparateCaches = SmbiosProcessorHasSeparateCaches (CacheLevel);
|
|
|
|
// At each level of cache, we can have a single type (unified, instruction or data),
|
|
// or two types - separate data and instruction caches. If we have separate
|
|
// instruction and data caches, then on the first iteration (CacheSubLevel = 0)
|
|
// process the instruction cache.
|
|
for (DataCacheType = 0; DataCacheType <= 1; DataCacheType++) {
|
|
// If there's no separate data/instruction cache, skip the second iteration
|
|
if (DataCacheType == 1 && !SeparateCaches) {
|
|
continue;
|
|
}
|
|
|
|
Type7Record = AllocateAndInitCacheInformation (CacheLevel,
|
|
DataCacheType,
|
|
!SeparateCaches
|
|
);
|
|
if (Type7Record == NULL) {
|
|
continue;
|
|
}
|
|
|
|
ConfigureCacheArchitectureInformation(CacheLevel,
|
|
DataCacheType,
|
|
!SeparateCaches,
|
|
Type7Record
|
|
);
|
|
|
|
// Allow the platform to fill in other information such as speed, SRAM type etc.
|
|
if (!OemGetCacheInformation (ProcessorIndex, CacheLevel,
|
|
DataCacheType, !SeparateCaches, Type7Record)) {
|
|
continue;
|
|
}
|
|
|
|
SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
|
|
// Finally, install the table
|
|
Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle,
|
|
(EFI_SMBIOS_TABLE_HEADER *)Type7Record);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
// Config L1/L2/L3 Cache Handle
|
|
switch (CacheLevel) {
|
|
case CpuCacheL1:
|
|
*L1CacheHandle = SmbiosHandle;
|
|
break;
|
|
case CpuCacheL2:
|
|
*L2CacheHandle = SmbiosHandle;
|
|
break;
|
|
case CpuCacheL3:
|
|
*L3CacheHandle = SmbiosHandle;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Allocates a Type 4 Processor Information structure and sets the
|
|
strings following the data fields.
|
|
|
|
@param[out] Type4Record The Type 4 structure to allocate and initialize
|
|
@param[in] ProcessorIndex The index of the processor
|
|
@param[in] Populated Whether the specified processor is
|
|
populated.
|
|
|
|
@retval EFI_SUCCESS The Type 4 structure was successfully
|
|
allocated and the strings initialized.
|
|
@retval EFI_OUT_OF_RESOURCES Could not allocate memory needed.
|
|
**/
|
|
EFI_STATUS
|
|
AllocateType4AndSetProcessorInformationStrings (
|
|
SMBIOS_TABLE_TYPE4 **Type4Record,
|
|
UINT8 ProcessorIndex,
|
|
BOOLEAN Populated
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_STRING_ID ProcessorManu;
|
|
EFI_STRING_ID ProcessorVersion;
|
|
EFI_STRING_ID SerialNumber;
|
|
EFI_STRING_ID AssetTag;
|
|
EFI_STRING_ID PartNumber;
|
|
EFI_STRING ProcessorStr;
|
|
EFI_STRING ProcessorManuStr;
|
|
EFI_STRING ProcessorVersionStr;
|
|
EFI_STRING SerialNumberStr;
|
|
EFI_STRING AssetTagStr;
|
|
EFI_STRING PartNumberStr;
|
|
CHAR8 *OptionalStrStart;
|
|
CHAR8 *StrStart;
|
|
UINTN ProcessorStrLen;
|
|
UINTN ProcessorManuStrLen;
|
|
UINTN ProcessorVersionStrLen;
|
|
UINTN SerialNumberStrLen;
|
|
UINTN AssetTagStrLen;
|
|
UINTN PartNumberStrLen;
|
|
UINTN TotalSize;
|
|
UINTN StringBufferSize;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
ProcessorManuStr = NULL;
|
|
ProcessorVersionStr = NULL;
|
|
SerialNumberStr = NULL;
|
|
AssetTagStr = NULL;
|
|
PartNumberStr = NULL;
|
|
|
|
ProcessorManu = STRING_TOKEN (STR_PROCESSOR_MANUFACTURE);
|
|
ProcessorVersion = STRING_TOKEN (STR_PROCESSOR_VERSION);
|
|
SerialNumber = STRING_TOKEN (STR_PROCESSOR_SERIAL_NUMBER);
|
|
AssetTag = STRING_TOKEN (STR_PROCESSOR_ASSET_TAG);
|
|
PartNumber = STRING_TOKEN (STR_PROCESSOR_PART_NUMBER);
|
|
|
|
SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorManufacturer, ProcessorManu);
|
|
SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorVersion, ProcessorVersion);
|
|
SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorSerialNumber, SerialNumber);
|
|
SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorAssetTag, AssetTag);
|
|
SET_HII_STRING_IF_PCD_NOT_EMPTY (PcdProcessorPartNumber, PartNumber);
|
|
|
|
// Processor Designation
|
|
StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;
|
|
ProcessorStr = AllocateZeroPool (StringBufferSize);
|
|
if (ProcessorStr == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
ProcessorStrLen = UnicodeSPrint (ProcessorStr, StringBufferSize,
|
|
L"CPU%02d", ProcessorIndex + 1);
|
|
|
|
// Processor Manufacture
|
|
ProcessorManuStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorManu, NULL);
|
|
ProcessorManuStrLen = StrLen (ProcessorManuStr);
|
|
|
|
// Processor Version
|
|
ProcessorVersionStr = HiiGetPackageString (&gEfiCallerIdGuid, ProcessorVersion, NULL);
|
|
ProcessorVersionStrLen = StrLen (ProcessorVersionStr);
|
|
|
|
// Serial Number
|
|
SerialNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, SerialNumber, NULL);
|
|
SerialNumberStrLen = StrLen (SerialNumberStr);
|
|
|
|
// Asset Tag
|
|
AssetTagStr = HiiGetPackageString (&gEfiCallerIdGuid, AssetTag, NULL);
|
|
AssetTagStrLen = StrLen (AssetTagStr);
|
|
|
|
// Part Number
|
|
PartNumberStr = HiiGetPackageString (&gEfiCallerIdGuid, PartNumber, NULL);
|
|
PartNumberStrLen = StrLen (PartNumberStr);
|
|
|
|
TotalSize = sizeof (SMBIOS_TABLE_TYPE4) +
|
|
ProcessorStrLen + 1 +
|
|
ProcessorManuStrLen + 1 +
|
|
ProcessorVersionStrLen + 1 +
|
|
SerialNumberStrLen + 1 +
|
|
AssetTagStrLen + 1 +
|
|
PartNumberStrLen + 1 + 1;
|
|
|
|
*Type4Record = AllocateZeroPool (TotalSize);
|
|
if (*Type4Record == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Exit;
|
|
}
|
|
|
|
CopyMem (*Type4Record, &mSmbiosProcessorTableTemplate, sizeof (SMBIOS_TABLE_TYPE4));
|
|
|
|
OptionalStrStart = (CHAR8 *)(*Type4Record + 1);
|
|
UnicodeStrToAsciiStrS (
|
|
ProcessorStr,
|
|
OptionalStrStart,
|
|
ProcessorStrLen + 1
|
|
);
|
|
|
|
StrStart = OptionalStrStart + ProcessorStrLen + 1;
|
|
UnicodeStrToAsciiStrS (
|
|
ProcessorManuStr,
|
|
StrStart,
|
|
ProcessorManuStrLen + 1
|
|
);
|
|
|
|
StrStart += ProcessorManuStrLen + 1;
|
|
UnicodeStrToAsciiStrS (
|
|
ProcessorVersionStr,
|
|
StrStart,
|
|
ProcessorVersionStrLen + 1
|
|
);
|
|
|
|
StrStart += ProcessorVersionStrLen + 1;
|
|
UnicodeStrToAsciiStrS (
|
|
SerialNumberStr,
|
|
StrStart,
|
|
SerialNumberStrLen + 1
|
|
);
|
|
|
|
StrStart += SerialNumberStrLen + 1;
|
|
UnicodeStrToAsciiStrS (
|
|
AssetTagStr,
|
|
StrStart,
|
|
AssetTagStrLen + 1
|
|
);
|
|
|
|
StrStart += AssetTagStrLen + 1;
|
|
UnicodeStrToAsciiStrS (
|
|
PartNumberStr,
|
|
StrStart,
|
|
PartNumberStrLen + 1
|
|
);
|
|
|
|
Exit:
|
|
FreePool (ProcessorStr);
|
|
FreePool (ProcessorManuStr);
|
|
FreePool (ProcessorVersionStr);
|
|
FreePool (SerialNumberStr);
|
|
FreePool (AssetTagStr);
|
|
FreePool (PartNumberStr);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Add Type 4 SMBIOS Record for Processor Information.
|
|
|
|
@param[in] ProcessorIndex Processor index of specified processor.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
AddSmbiosProcessorTypeTable (
|
|
IN UINTN ProcessorIndex
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
SMBIOS_TABLE_TYPE4 *Type4Record;
|
|
EFI_SMBIOS_HANDLE SmbiosHandle;
|
|
EFI_SMBIOS_HANDLE L1CacheHandle;
|
|
EFI_SMBIOS_HANDLE L2CacheHandle;
|
|
EFI_SMBIOS_HANDLE L3CacheHandle;
|
|
UINT8 *LegacyVoltage;
|
|
PROCESSOR_STATUS_DATA ProcessorStatus;
|
|
UINT64 *ProcessorId;
|
|
PROCESSOR_CHARACTERISTIC_FLAGS ProcessorCharacteristics;
|
|
OEM_MISC_PROCESSOR_DATA MiscProcessorData;
|
|
BOOLEAN ProcessorPopulated;
|
|
|
|
Type4Record = NULL;
|
|
|
|
MiscProcessorData.Voltage = 0;
|
|
MiscProcessorData.CurrentSpeed = 0;
|
|
MiscProcessorData.CoreCount = 0;
|
|
MiscProcessorData.CoresEnabled = 0;
|
|
MiscProcessorData.ThreadCount = 0;
|
|
MiscProcessorData.MaxSpeed = 0;
|
|
L1CacheHandle = 0xFFFF;
|
|
L2CacheHandle = 0xFFFF;
|
|
L3CacheHandle = 0xFFFF;
|
|
|
|
ProcessorPopulated = OemIsProcessorPresent (ProcessorIndex);
|
|
|
|
Status = AllocateType4AndSetProcessorInformationStrings (
|
|
&Type4Record,
|
|
ProcessorIndex,
|
|
ProcessorPopulated
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
OemGetProcessorInformation (ProcessorIndex,
|
|
&ProcessorStatus,
|
|
(PROCESSOR_CHARACTERISTIC_FLAGS*)
|
|
&Type4Record->ProcessorCharacteristics,
|
|
&MiscProcessorData);
|
|
|
|
if (ProcessorPopulated) {
|
|
AddSmbiosCacheTypeTable (ProcessorIndex, &L1CacheHandle,
|
|
&L2CacheHandle, &L3CacheHandle);
|
|
}
|
|
|
|
LegacyVoltage = (UINT8*)&Type4Record->Voltage;
|
|
|
|
*LegacyVoltage = MiscProcessorData.Voltage;
|
|
Type4Record->CurrentSpeed = MiscProcessorData.CurrentSpeed;
|
|
Type4Record->MaxSpeed = MiscProcessorData.MaxSpeed;
|
|
Type4Record->Status = ProcessorStatus.Data;
|
|
Type4Record->L1CacheHandle = L1CacheHandle;
|
|
Type4Record->L2CacheHandle = L2CacheHandle;
|
|
Type4Record->L3CacheHandle = L3CacheHandle;
|
|
Type4Record->CoreCount = MiscProcessorData.CoreCount;
|
|
Type4Record->CoreCount2 = MiscProcessorData.CoreCount;
|
|
Type4Record->EnabledCoreCount = MiscProcessorData.CoresEnabled;
|
|
Type4Record->EnabledCoreCount2 = MiscProcessorData.CoresEnabled;
|
|
Type4Record->ThreadCount = MiscProcessorData.ThreadCount;
|
|
Type4Record->ThreadCount2 = MiscProcessorData.ThreadCount;
|
|
|
|
Type4Record->CurrentSpeed = GetCpuFrequency (ProcessorIndex);
|
|
Type4Record->ExternalClock =
|
|
(UINT16)(SmbiosGetExternalClockFrequency () / 1000 / 1000);
|
|
|
|
ProcessorId = (UINT64*)&Type4Record->ProcessorId;
|
|
*ProcessorId = SmbiosGetProcessorId ();
|
|
|
|
ProcessorCharacteristics = SmbiosGetProcessorCharacteristics ();
|
|
Type4Record->ProcessorCharacteristics |= *((UINT64*)&ProcessorCharacteristics);
|
|
|
|
Type4Record->ProcessorFamily = SmbiosGetProcessorFamily ();
|
|
Type4Record->ProcessorFamily2 = SmbiosGetProcessorFamily2 ();
|
|
|
|
SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
|
|
Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle,
|
|
(EFI_SMBIOS_TABLE_HEADER *)Type4Record);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "[%a]:[%dL] Smbios Type04 Table Log Failed! %r \n",
|
|
__FUNCTION__, __LINE__, Status));
|
|
}
|
|
FreePool (Type4Record);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Standard EFI driver point.
|
|
|
|
@param ImageHandle Handle for the image of this driver
|
|
@param SystemTable Pointer to the EFI System Table
|
|
|
|
@retval EFI_SUCCESS The data was successfully stored.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ProcessorSubClassEntryPoint(
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT32 ProcessorIndex;
|
|
|
|
//
|
|
// Locate dependent protocols
|
|
//
|
|
Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID**)&mSmbios);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "Could not locate SMBIOS protocol. %r\n", Status));
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Add our default strings to the HII database. They will be modified later.
|
|
//
|
|
mHiiHandle = HiiAddPackages (&gEfiCallerIdGuid,
|
|
NULL,
|
|
ProcessorSubClassStrings,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (mHiiHandle == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Add SMBIOS tables for populated sockets.
|
|
//
|
|
for (ProcessorIndex = 0; ProcessorIndex < OemGetMaxProcessors (); ProcessorIndex++) {
|
|
Status = AddSmbiosProcessorTypeTable (ProcessorIndex);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "Add Processor Type Table Failed! %r.\n", Status));
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|