ArmPkg: Add Universal/Smbios/ProcessorSubClassDxe
ProcessorSubClassDxe provides SMBIOS CPU information using generic methods combined with calls into OemMiscLib. Signed-off-by: Rebecca Cran <rebecca@nuviainc.com> Reviewed-by: Samer El-Haj-Mahmoud <Samer.El-Haj-Mahmoud@arm.com>
This commit is contained in:
committed by
mergify[bot]
parent
0e51d7e445
commit
2ba6ecef39
@ -148,6 +148,8 @@
|
|||||||
ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.inf
|
ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.inf
|
||||||
ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf
|
ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf
|
||||||
|
|
||||||
|
ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf
|
||||||
|
|
||||||
[Components.AARCH64]
|
[Components.AARCH64]
|
||||||
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
|
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
|
||||||
ArmPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf
|
ArmPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf
|
||||||
|
752
ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
Normal file
752
ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
Normal file
@ -0,0 +1,752 @@
|
|||||||
|
/** @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 socket
|
||||||
|
@param[in] Populated Whether the specified processor socket 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 ProcessorSocketStr;
|
||||||
|
EFI_STRING ProcessorManuStr;
|
||||||
|
EFI_STRING ProcessorVersionStr;
|
||||||
|
EFI_STRING SerialNumberStr;
|
||||||
|
EFI_STRING AssetTagStr;
|
||||||
|
EFI_STRING PartNumberStr;
|
||||||
|
CHAR8 *OptionalStrStart;
|
||||||
|
CHAR8 *StrStart;
|
||||||
|
UINTN ProcessorSocketStrLen;
|
||||||
|
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 Socket Designation
|
||||||
|
StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;
|
||||||
|
ProcessorSocketStr = AllocateZeroPool (StringBufferSize);
|
||||||
|
if (ProcessorSocketStr == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessorSocketStrLen = UnicodeSPrint (ProcessorSocketStr, 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) +
|
||||||
|
ProcessorSocketStrLen + 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 (
|
||||||
|
ProcessorSocketStr,
|
||||||
|
OptionalStrStart,
|
||||||
|
ProcessorSocketStrLen + 1
|
||||||
|
);
|
||||||
|
|
||||||
|
StrStart = OptionalStrStart + ProcessorSocketStrLen + 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 (ProcessorSocketStr);
|
||||||
|
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 SocketPopulated;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
SocketPopulated = OemIsSocketPresent(ProcessorIndex);
|
||||||
|
|
||||||
|
Status = AllocateType4AndSetProcessorInformationStrings (
|
||||||
|
&Type4Record,
|
||||||
|
ProcessorIndex,
|
||||||
|
SocketPopulated
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
OemGetProcessorInformation (ProcessorIndex,
|
||||||
|
&ProcessorStatus,
|
||||||
|
(PROCESSOR_CHARACTERISTIC_FLAGS*)
|
||||||
|
&Type4Record->ProcessorCharacteristics,
|
||||||
|
&MiscProcessorData);
|
||||||
|
|
||||||
|
if (SocketPopulated) {
|
||||||
|
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 SocketIndex;
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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 (SocketIndex = 0; SocketIndex < OemGetProcessorMaxSockets(); SocketIndex++) {
|
||||||
|
Status = AddSmbiosProcessorTypeTable (SocketIndex);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
DEBUG ((DEBUG_ERROR, "Add Processor Type Table Failed! %r.\n", Status));
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
#/** @file
|
||||||
|
# ProcessorSubClassDxe.inf
|
||||||
|
#
|
||||||
|
# Copyright (c) 2021, NUVIA Inc. All rights reserved.
|
||||||
|
# Copyright (c) 2015, Hisilicon Limited. All rights reserved.
|
||||||
|
# Copyright (c) 2015, Linaro Limited. All rights reserved.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
#
|
||||||
|
#**/
|
||||||
|
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 1.29
|
||||||
|
BASE_NAME = ProcessorSubClass
|
||||||
|
FILE_GUID = f3fe0e33-ea38-4069-9fb5-be23407207c7
|
||||||
|
MODULE_TYPE = DXE_DRIVER
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
ENTRY_POINT = ProcessorSubClassEntryPoint
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
SmbiosProcessorArmCommon.c
|
||||||
|
ProcessorSubClass.c
|
||||||
|
ProcessorSubClassStrings.uni
|
||||||
|
SmbiosProcessor.h
|
||||||
|
|
||||||
|
[Sources.AARCH64]
|
||||||
|
SmbiosProcessorAArch64.c
|
||||||
|
|
||||||
|
[Sources.ARM]
|
||||||
|
SmbiosProcessorArm.c
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
ArmPkg/ArmPkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
ArmLib
|
||||||
|
ArmSmcLib
|
||||||
|
BaseLib
|
||||||
|
BaseMemoryLib
|
||||||
|
DebugLib
|
||||||
|
HiiLib
|
||||||
|
IoLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
OemMiscLib
|
||||||
|
PcdLib
|
||||||
|
PrintLib
|
||||||
|
UefiDriverEntryPoint
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gArmTokenSpaceGuid.PcdProcessorManufacturer
|
||||||
|
gArmTokenSpaceGuid.PcdProcessorVersion
|
||||||
|
gArmTokenSpaceGuid.PcdProcessorSerialNumber
|
||||||
|
gArmTokenSpaceGuid.PcdProcessorAssetTag
|
||||||
|
gArmTokenSpaceGuid.PcdProcessorPartNumber
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
gEfiSmbiosProtocolGuid
|
@ -0,0 +1,24 @@
|
|||||||
|
/** @file
|
||||||
|
SMBIOS Type 4 strings
|
||||||
|
|
||||||
|
Copyright (c) 2021, NUVIA Inc. All rights reserved.
|
||||||
|
Copyright (c) 2015, Hisilicon Limited. All rights reserved.
|
||||||
|
Copyright (c) 2015, Linaro Limited. All rights reserved.
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
/=#
|
||||||
|
|
||||||
|
#langdef en-US "English"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Processor Information
|
||||||
|
//
|
||||||
|
#string STR_PROCESSOR_SOCKET_DESIGNATION #language en-US "Not Specified"
|
||||||
|
#string STR_PROCESSOR_MANUFACTURE #language en-US "Not Specified"
|
||||||
|
#string STR_PROCESSOR_VERSION #language en-US "Not Specified"
|
||||||
|
#string STR_PROCESSOR_SERIAL_NUMBER #language en-US "Not Specified"
|
||||||
|
#string STR_PROCESSOR_ASSET_TAG #language en-US "Not Specified"
|
||||||
|
#string STR_PROCESSOR_PART_NUMBER #language en-US "Not Specified"
|
||||||
|
#string STR_PROCESSOR_UNKNOWN #language en-US "Unknown"
|
102
ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessor.h
Normal file
102
ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessor.h
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
/** @file
|
||||||
|
SMBIOS Processor Related Functions.
|
||||||
|
|
||||||
|
Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef SMBIOS_PROCESSOR_H_
|
||||||
|
#define SMBIOS_PROCESSOR_H_
|
||||||
|
|
||||||
|
#include <Uefi.h>
|
||||||
|
#include <IndustryStandard/SmBios.h>
|
||||||
|
|
||||||
|
/** Returns the maximum cache level implemented by the current CPU.
|
||||||
|
|
||||||
|
@return The maximum cache level implemented.
|
||||||
|
**/
|
||||||
|
UINT8
|
||||||
|
SmbiosProcessorGetMaxCacheLevel (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Returns whether or not the specified cache level has separate I/D caches.
|
||||||
|
|
||||||
|
@param CacheLevel The cache level (L1, L2 etc.).
|
||||||
|
|
||||||
|
@return TRUE if the cache level has separate I/D caches, FALSE otherwise.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
SmbiosProcessorHasSeparateCaches (
|
||||||
|
UINT8 CacheLevel
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Gets the size of the specified cache.
|
||||||
|
|
||||||
|
@param CacheLevel The cache level (L1, L2 etc.).
|
||||||
|
@param DataCache Whether the cache is a dedicated data cache.
|
||||||
|
@param UnifiedCache Whether the cache is a unified cache.
|
||||||
|
|
||||||
|
@return The cache size.
|
||||||
|
**/
|
||||||
|
UINT64
|
||||||
|
SmbiosProcessorGetCacheSize (
|
||||||
|
IN UINT8 CacheLevel,
|
||||||
|
IN BOOLEAN DataCache,
|
||||||
|
IN BOOLEAN UnifiedCache
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Gets the associativity of the specified cache.
|
||||||
|
|
||||||
|
@param CacheLevel The cache level (L1, L2 etc.).
|
||||||
|
@param DataCache Whether the cache is a dedicated data cache.
|
||||||
|
@param UnifiedCache Whether the cache is a unified cache.
|
||||||
|
|
||||||
|
@return The cache associativity.
|
||||||
|
**/
|
||||||
|
UINT32
|
||||||
|
SmbiosProcessorGetCacheAssociativity (
|
||||||
|
IN UINT8 CacheLevel,
|
||||||
|
IN BOOLEAN DataCache,
|
||||||
|
IN BOOLEAN UnifiedCache
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Returns a value for the Processor ID field that conforms to SMBIOS
|
||||||
|
requirements.
|
||||||
|
|
||||||
|
@return Processor ID.
|
||||||
|
**/
|
||||||
|
UINT64
|
||||||
|
SmbiosGetProcessorId (VOID);
|
||||||
|
|
||||||
|
/** Returns the external clock frequency.
|
||||||
|
|
||||||
|
@return The external CPU clock frequency.
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
SmbiosGetExternalClockFrequency (VOID);
|
||||||
|
|
||||||
|
/** Returns the SMBIOS ProcessorFamily field value.
|
||||||
|
|
||||||
|
@return The value for the ProcessorFamily field.
|
||||||
|
**/
|
||||||
|
UINT8
|
||||||
|
SmbiosGetProcessorFamily (VOID);
|
||||||
|
|
||||||
|
/** Returns the ProcessorFamily2 field value.
|
||||||
|
|
||||||
|
@return The value for the ProcessorFamily2 field.
|
||||||
|
**/
|
||||||
|
UINT16
|
||||||
|
SmbiosGetProcessorFamily2 (VOID);
|
||||||
|
|
||||||
|
/** Returns the SMBIOS Processor Characteristics.
|
||||||
|
|
||||||
|
@return Processor Characteristics bitfield.
|
||||||
|
**/
|
||||||
|
PROCESSOR_CHARACTERISTIC_FLAGS
|
||||||
|
SmbiosGetProcessorCharacteristics (VOID);
|
||||||
|
|
||||||
|
#endif // SMBIOS_PROCESSOR_H_
|
@ -0,0 +1,93 @@
|
|||||||
|
/** @file
|
||||||
|
Functions for AARCH64 processor information
|
||||||
|
|
||||||
|
Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <Uefi.h>
|
||||||
|
#include <Library/ArmLib.h>
|
||||||
|
#include <Library/ArmLib/ArmLibPrivate.h>
|
||||||
|
|
||||||
|
#include "SmbiosProcessor.h"
|
||||||
|
|
||||||
|
/** Gets the size of the specified cache.
|
||||||
|
|
||||||
|
@param CacheLevel The cache level (L1, L2 etc.).
|
||||||
|
@param DataCache Whether the cache is a dedicated data cache.
|
||||||
|
@param UnifiedCache Whether the cache is a unified cache.
|
||||||
|
|
||||||
|
@return The cache size.
|
||||||
|
**/
|
||||||
|
UINT64
|
||||||
|
SmbiosProcessorGetCacheSize (
|
||||||
|
IN UINT8 CacheLevel,
|
||||||
|
IN BOOLEAN DataCache,
|
||||||
|
IN BOOLEAN UnifiedCache
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CCSIDR_DATA Ccsidr;
|
||||||
|
CSSELR_DATA Csselr;
|
||||||
|
BOOLEAN CcidxSupported;
|
||||||
|
UINT64 CacheSize;
|
||||||
|
|
||||||
|
Csselr.Data = 0;
|
||||||
|
Csselr.Bits.Level = CacheLevel - 1;
|
||||||
|
Csselr.Bits.InD = (!DataCache && !UnifiedCache);
|
||||||
|
|
||||||
|
Ccsidr.Data = ReadCCSIDR (Csselr.Data);
|
||||||
|
|
||||||
|
CcidxSupported = ArmHasCcidx ();
|
||||||
|
|
||||||
|
if (CcidxSupported) {
|
||||||
|
CacheSize = (1 << (Ccsidr.BitsCcidxAA64.LineSize + 4)) *
|
||||||
|
(Ccsidr.BitsCcidxAA64.Associativity + 1) *
|
||||||
|
(Ccsidr.BitsCcidxAA64.NumSets + 1);
|
||||||
|
} else {
|
||||||
|
CacheSize = (1 << (Ccsidr.BitsNonCcidx.LineSize + 4)) *
|
||||||
|
(Ccsidr.BitsNonCcidx.Associativity + 1) *
|
||||||
|
(Ccsidr.BitsNonCcidx.NumSets + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CacheSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the associativity of the specified cache.
|
||||||
|
|
||||||
|
@param CacheLevel The cache level (L1, L2 etc.).
|
||||||
|
@param DataCache Whether the cache is a dedicated data cache.
|
||||||
|
@param UnifiedCache Whether the cache is a unified cache.
|
||||||
|
|
||||||
|
@return The cache associativity.
|
||||||
|
**/
|
||||||
|
UINT32
|
||||||
|
SmbiosProcessorGetCacheAssociativity (
|
||||||
|
IN UINT8 CacheLevel,
|
||||||
|
IN BOOLEAN DataCache,
|
||||||
|
IN BOOLEAN UnifiedCache
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CCSIDR_DATA Ccsidr;
|
||||||
|
CSSELR_DATA Csselr;
|
||||||
|
BOOLEAN CcidxSupported;
|
||||||
|
UINT32 Associativity;
|
||||||
|
|
||||||
|
Csselr.Data = 0;
|
||||||
|
Csselr.Bits.Level = CacheLevel - 1;
|
||||||
|
Csselr.Bits.InD = (!DataCache && !UnifiedCache);
|
||||||
|
|
||||||
|
Ccsidr.Data = ReadCCSIDR (Csselr.Data);
|
||||||
|
|
||||||
|
CcidxSupported = ArmHasCcidx ();
|
||||||
|
|
||||||
|
if (CcidxSupported) {
|
||||||
|
Associativity = Ccsidr.BitsCcidxAA64.Associativity + 1;
|
||||||
|
} else {
|
||||||
|
Associativity = Ccsidr.BitsNonCcidx.Associativity + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Associativity;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
|||||||
|
/** @file
|
||||||
|
Functions for ARM processor information
|
||||||
|
|
||||||
|
Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <Uefi.h>
|
||||||
|
#include <Library/ArmLib.h>
|
||||||
|
#include <Library/ArmLib/ArmLibPrivate.h>
|
||||||
|
|
||||||
|
#include "SmbiosProcessor.h"
|
||||||
|
|
||||||
|
/** Gets the size of the specified cache.
|
||||||
|
|
||||||
|
@param CacheLevel The cache level (L1, L2 etc.).
|
||||||
|
@param DataCache Whether the cache is a dedicated data cache.
|
||||||
|
@param UnifiedCache Whether the cache is a unified cache.
|
||||||
|
|
||||||
|
@return The cache size.
|
||||||
|
**/
|
||||||
|
UINT64
|
||||||
|
ArmGetCacheSize (
|
||||||
|
IN UINT8 CacheLevel,
|
||||||
|
IN BOOLEAN DataCache,
|
||||||
|
IN BOOLEAN UnifiedCache
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CCSIDR_DATA Ccsidr;
|
||||||
|
CCSIDR2_DATA Ccsidr2;
|
||||||
|
CSSELR_DATA Csselr;
|
||||||
|
BOOLEAN CcidxSupported;
|
||||||
|
UINT64 CacheSize;
|
||||||
|
|
||||||
|
// Read the CCSIDR register to get the cache architecture
|
||||||
|
Csselr.Data = 0;
|
||||||
|
Csselr.Bits.Level = CacheLevel - 1;
|
||||||
|
Csselr.Bits.InD = (!DataCache && !UnifiedCache);
|
||||||
|
|
||||||
|
Ccsidr.Data = ReadCCSIDR (Csselr.Data);
|
||||||
|
|
||||||
|
CcidxSupported = ArmHasCcidx ();
|
||||||
|
|
||||||
|
if (CcidxSupported) {
|
||||||
|
Ccsidr2.Data = ReadCCSIDR2 (Csselr.Data);
|
||||||
|
CacheSize = (1 << (Ccsidr.BitsCcidxAA32.LineSize + 4)) *
|
||||||
|
(Ccsidr.BitsCcidxAA32.Associativity + 1) *
|
||||||
|
(Ccsidr2.Bits.NumSets + 1);
|
||||||
|
} else {
|
||||||
|
CacheSize = (1 << (Ccsidr.BitsNonCcidx.LineSize + 4)) *
|
||||||
|
(Ccsidr.BitsNonCcidx.Associativity + 1) *
|
||||||
|
(Ccsidr.BitsNonCcidx.NumSets + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CacheSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the associativity of the specified cache.
|
||||||
|
|
||||||
|
@param CacheLevel The cache level (L1, L2 etc.).
|
||||||
|
@param DataCache Whether the cache is a dedicated data cache.
|
||||||
|
@param UnifiedCache Whether the cache is a unified cache.
|
||||||
|
|
||||||
|
@return The cache associativity.
|
||||||
|
**/
|
||||||
|
UINT32
|
||||||
|
ArmGetCacheAssociativity (
|
||||||
|
IN UINT8 CacheLevel,
|
||||||
|
IN BOOLEAN DataCache,
|
||||||
|
IN BOOLEAN UnifiedCache
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CCSIDR_DATA Ccsidr;
|
||||||
|
CCSIDR2_DATA Ccsidr2;
|
||||||
|
CSSELR_DATA Csselr;
|
||||||
|
BOOLEAN CcidxSupported;
|
||||||
|
UINT32 Associativity;
|
||||||
|
|
||||||
|
// Read the CCSIDR register to get the cache architecture
|
||||||
|
Csselr.Data = 0;
|
||||||
|
Csselr.Bits.Level = CacheLevel - 1;
|
||||||
|
Csselr.Bits.InD = (!DataCache && !UnifiedCache);
|
||||||
|
|
||||||
|
Ccsidr.Data = ReadCCSIDR (Csselr.Data);
|
||||||
|
|
||||||
|
CcidxSupported = ArmHasCcidx ();
|
||||||
|
|
||||||
|
if (CcidxSupported) {
|
||||||
|
Ccsidr2.Data = ReadCCSIDR2 (Csselr.Data);
|
||||||
|
Associativity = Ccsidr.BitsCcidxAA32.Associativity + 1;
|
||||||
|
} else {
|
||||||
|
Associativity = Ccsidr.BitsNonCcidx.Associativity + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Associativity;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,249 @@
|
|||||||
|
/** @file
|
||||||
|
Functions for processor information common to ARM and AARCH64.
|
||||||
|
|
||||||
|
Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <Uefi.h>
|
||||||
|
#include <IndustryStandard/ArmStdSmc.h>
|
||||||
|
#include <IndustryStandard/SmBios.h>
|
||||||
|
#include <Library/ArmLib.h>
|
||||||
|
#include <Library/ArmLib/ArmLibPrivate.h>
|
||||||
|
#include <Library/ArmSmcLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
|
||||||
|
#include "SmbiosProcessor.h"
|
||||||
|
|
||||||
|
/** Returns the maximum cache level implemented by the current CPU.
|
||||||
|
|
||||||
|
@return The maximum cache level implemented.
|
||||||
|
**/
|
||||||
|
UINT8
|
||||||
|
SmbiosProcessorGetMaxCacheLevel (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CLIDR_DATA Clidr;
|
||||||
|
UINT8 CacheLevel;
|
||||||
|
UINT8 MaxCacheLevel;
|
||||||
|
|
||||||
|
MaxCacheLevel = 0;
|
||||||
|
|
||||||
|
// Read the CLIDR register to find out what caches are present.
|
||||||
|
Clidr.Data = ReadCLIDR ();
|
||||||
|
|
||||||
|
// Get the cache type for the L1 cache. If it's 0, there are no caches.
|
||||||
|
if (CLIDR_GET_CACHE_TYPE (Clidr.Data, 1) == ClidrCacheTypeNone) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CacheLevel = 1; CacheLevel <= MAX_ARM_CACHE_LEVEL; CacheLevel++) {
|
||||||
|
if (CLIDR_GET_CACHE_TYPE (Clidr.Data, CacheLevel) == ClidrCacheTypeNone) {
|
||||||
|
MaxCacheLevel = CacheLevel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MaxCacheLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns whether or not the specified cache level has separate I/D caches.
|
||||||
|
|
||||||
|
@param CacheLevel The cache level (L1, L2 etc.).
|
||||||
|
|
||||||
|
@return TRUE if the cache level has separate I/D caches, FALSE otherwise.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
SmbiosProcessorHasSeparateCaches (
|
||||||
|
UINT8 CacheLevel
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CLIDR_CACHE_TYPE CacheType;
|
||||||
|
CLIDR_DATA Clidr;
|
||||||
|
BOOLEAN SeparateCaches;
|
||||||
|
|
||||||
|
SeparateCaches = FALSE;
|
||||||
|
|
||||||
|
Clidr.Data = ReadCLIDR ();
|
||||||
|
|
||||||
|
CacheType = CLIDR_GET_CACHE_TYPE (Clidr.Data, CacheLevel - 1);
|
||||||
|
|
||||||
|
if (CacheType == ClidrCacheTypeSeparate) {
|
||||||
|
SeparateCaches = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SeparateCaches;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if ther ARM64 SoC ID SMC call is supported
|
||||||
|
|
||||||
|
@return Whether the ARM64 SoC ID call is supported.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
HasSmcArm64SocId (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ARM_SMC_ARGS Args;
|
||||||
|
INT32 SmcCallStatus;
|
||||||
|
BOOLEAN Arm64SocIdSupported;
|
||||||
|
|
||||||
|
Arm64SocIdSupported = FALSE;
|
||||||
|
|
||||||
|
Args.Arg0 = SMCCC_VERSION;
|
||||||
|
ArmCallSmc (&Args);
|
||||||
|
SmcCallStatus = (INT32)Args.Arg0;
|
||||||
|
|
||||||
|
if (SmcCallStatus < 0 || (SmcCallStatus >> 16) >= 1) {
|
||||||
|
Args.Arg0 = SMCCC_ARCH_FEATURES;
|
||||||
|
Args.Arg1 = SMCCC_ARCH_SOC_ID;
|
||||||
|
ArmCallSmc (&Args);
|
||||||
|
|
||||||
|
if (Args.Arg0 >= 0) {
|
||||||
|
Arm64SocIdSupported = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Arm64SocIdSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fetches the JEP106 code and SoC Revision.
|
||||||
|
|
||||||
|
@param Jep106Code JEP 106 code.
|
||||||
|
@param SocRevision SoC revision.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Succeeded.
|
||||||
|
@retval EFI_UNSUPPORTED Failed.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
SmbiosGetSmcArm64SocId (
|
||||||
|
OUT INT32 *Jep106Code,
|
||||||
|
OUT INT32 *SocRevision
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ARM_SMC_ARGS Args;
|
||||||
|
INT32 SmcCallStatus;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
|
||||||
|
Args.Arg0 = SMCCC_ARCH_SOC_ID;
|
||||||
|
Args.Arg1 = 0;
|
||||||
|
ArmCallSmc (&Args);
|
||||||
|
SmcCallStatus = (INT32)Args.Arg0;
|
||||||
|
|
||||||
|
if (SmcCallStatus >= 0) {
|
||||||
|
*Jep106Code = (INT32)Args.Arg0;
|
||||||
|
} else {
|
||||||
|
Status = EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Args.Arg0 = SMCCC_ARCH_SOC_ID;
|
||||||
|
Args.Arg1 = 1;
|
||||||
|
ArmCallSmc (&Args);
|
||||||
|
SmcCallStatus = (INT32)Args.Arg0;
|
||||||
|
|
||||||
|
if (SmcCallStatus >= 0) {
|
||||||
|
*SocRevision = (INT32)Args.Arg0;
|
||||||
|
} else {
|
||||||
|
Status = EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns a value for the Processor ID field that conforms to SMBIOS
|
||||||
|
requirements.
|
||||||
|
|
||||||
|
@return Processor ID.
|
||||||
|
**/
|
||||||
|
UINT64
|
||||||
|
SmbiosGetProcessorId (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
INT32 Jep106Code;
|
||||||
|
INT32 SocRevision;
|
||||||
|
UINT64 ProcessorId;
|
||||||
|
|
||||||
|
if (HasSmcArm64SocId ()) {
|
||||||
|
SmbiosGetSmcArm64SocId (&Jep106Code, &SocRevision);
|
||||||
|
ProcessorId = ((UINT64)Jep106Code << 32) | SocRevision;
|
||||||
|
} else {
|
||||||
|
ProcessorId = ArmReadMidr ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the external clock frequency.
|
||||||
|
|
||||||
|
@return The external clock frequency.
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
SmbiosGetExternalClockFrequency (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return ArmReadCntFrq ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the SMBIOS ProcessorFamily field value.
|
||||||
|
|
||||||
|
@return The value for the ProcessorFamily field.
|
||||||
|
**/
|
||||||
|
UINT8
|
||||||
|
SmbiosGetProcessorFamily (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return ProcessorFamilyIndicatorFamily2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the ProcessorFamily2 field value.
|
||||||
|
|
||||||
|
@return The value for the ProcessorFamily2 field.
|
||||||
|
**/
|
||||||
|
UINT16
|
||||||
|
SmbiosGetProcessorFamily2 (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN MainIdRegister;
|
||||||
|
UINT16 ProcessorFamily2;
|
||||||
|
|
||||||
|
MainIdRegister = ArmReadMidr ();
|
||||||
|
|
||||||
|
if (((MainIdRegister >> 16) & 0xF) < 8) {
|
||||||
|
ProcessorFamily2 = ProcessorFamilyARM;
|
||||||
|
} else {
|
||||||
|
if (sizeof (VOID*) == 4) {
|
||||||
|
ProcessorFamily2 = ProcessorFamilyARMv7;
|
||||||
|
} else {
|
||||||
|
ProcessorFamily2 = ProcessorFamilyARMv8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ProcessorFamily2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the SMBIOS Processor Characteristics.
|
||||||
|
|
||||||
|
@return Processor Characteristics bitfield.
|
||||||
|
**/
|
||||||
|
PROCESSOR_CHARACTERISTIC_FLAGS
|
||||||
|
SmbiosGetProcessorCharacteristics (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PROCESSOR_CHARACTERISTIC_FLAGS Characteristics;
|
||||||
|
|
||||||
|
ZeroMem (&Characteristics, sizeof (Characteristics));
|
||||||
|
|
||||||
|
Characteristics.ProcessorArm64SocId = HasSmcArm64SocId ();
|
||||||
|
|
||||||
|
return Characteristics;
|
||||||
|
}
|
Reference in New Issue
Block a user