From: "Rebecca Cran" <rebecca@nuviainc.com>
To: devel@edk2.groups.io
Cc: "Rebecca Cran" <rebecca@nuviainc.com>,
leif@nuviainc.com, "Ard Biesheuvel" <ard.biesheuvel@arm.com>,
nd@arm.com, "Sami Mujawar" <Sami.Mujawar@arm.com>,
"Liming Gao" <gaoliming@byosoft.com.cn>,
"Michael D Kinney" <michael.d.kinney@intel.com>,
"Zhiguang Liu" <zhiguang.liu@intel.com>,
"Samer El-Haj-Mahmoud" <Samer.El-Haj-Mahmoud@arm.com>,
"Philippe Mathieu-Daudé" <philmd@redhat.com>
Subject: [PATCH v7 13/21] ArmPkg: Add Universal/Smbios/ProcessorSubClassDxe
Date: Sun, 31 Jan 2021 16:25:03 -0700 [thread overview]
Message-ID: <20210131232511.18340-14-rebecca@nuviainc.com> (raw)
In-Reply-To: <20210131232511.18340-1-rebecca@nuviainc.com>
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>
---
ArmPkg/ArmPkg.dsc | 2 +
ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf | 65 ++
ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessor.h | 106 +++
ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c | 766 ++++++++++++++++++++
ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorAArch64.c | 97 +++
ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArm.c | 103 +++
ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArmCommon.c | 250 +++++++
ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni | 24 +
8 files changed, 1413 insertions(+)
diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc
index 0f77a6da4483..fce86cb6d710 100644
--- a/ArmPkg/ArmPkg.dsc
+++ b/ArmPkg/ArmPkg.dsc
@@ -148,6 +148,8 @@ [Components.common]
ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.inf
ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf
+ ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf
+
[Components.AARCH64]
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
ArmPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf
diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf
new file mode 100644
index 000000000000..d74e365375b3
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf
@@ -0,0 +1,65 @@
+#/** @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
+
+[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
diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessor.h b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessor.h
new file mode 100644
index 000000000000..002fd6cc142b
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessor.h
@@ -0,0 +1,106 @@
+/** @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.). Zero based.
+
+ @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.). Zero based.
+ @param InstructionCache Whether the cache is a dedicated instruction cache.
+ @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 InstructionCache,
+ IN BOOLEAN DataCache,
+ IN BOOLEAN UnifiedCache
+ );
+
+/** Gets the associativity of the specified cache.
+
+ @param CacheLevel The cache level (L1, L2 etc.). Zero based.
+ @param InstructionCache Whether the cache is a dedicated instruction cache.
+ @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 InstructionCache,
+ 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_
diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
new file mode 100644
index 000000000000..ca55bc019f96
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClass.c
@@ -0,0 +1,766 @@
+/** @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] InstructionCache Cache is an instruction cache.
+ @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 InstructionCache,
+ IN BOOLEAN DataCache,
+ IN BOOLEAN UnifiedCache,
+ OUT CHAR16 *CacheSocketStr
+ )
+{
+ UINTN CacheSocketStrLen;
+
+ if (CacheLevel == CpuCacheL1 && InstructionCache) {
+ CacheSocketStrLen = UnicodeSPrint (
+ CacheSocketStr,
+ SMBIOS_STRING_MAX_LENGTH - 1,
+ L"L%x Instruction Cache",
+ CacheLevel + 1);
+ } else if (CacheLevel == CpuCacheL1 && DataCache) {
+ CacheSocketStrLen = UnicodeSPrint (CacheSocketStr,
+ SMBIOS_STRING_MAX_LENGTH - 1,
+ L"L%x Data Cache",
+ CacheLevel + 1);
+ } else {
+ CacheSocketStrLen = UnicodeSPrint (CacheSocketStr,
+ SMBIOS_STRING_MAX_LENGTH - 1,
+ L"L%x Cache",
+ CacheLevel + 1);
+ }
+
+ 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] InstructionCache Cache is an instruction cache.
+ @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 InstructionCache,
+ IN BOOLEAN DataCache,
+ IN BOOLEAN UnifiedCache,
+ OUT SMBIOS_TABLE_TYPE7 *Type7Record
+ )
+{
+ UINT8 Associativity;
+ UINT32 CacheSize32;
+ UINT16 CacheSize16;
+ UINT64 CacheSize64;
+
+ ASSERT (InstructionCache || DataCache || UnifiedCache);
+
+ if (InstructionCache) {
+ Type7Record->SystemCacheType = CacheTypeInstruction;
+ } else if (DataCache) {
+ Type7Record->SystemCacheType = CacheTypeData;
+ } else if (UnifiedCache) {
+ Type7Record->SystemCacheType = CacheTypeUnified;
+ } else {
+ ASSERT(FALSE);
+ }
+
+ CacheSize64 = SmbiosProcessorGetCacheSize (CacheLevel,
+ InstructionCache,
+ DataCache,
+ UnifiedCache
+ );
+
+ Associativity = SmbiosProcessorGetCacheAssociativity (CacheLevel,
+ InstructionCache,
+ 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->Associativity = Associativity + 1;
+ Type7Record->MaximumCacheSize = CacheSize16;
+ Type7Record->InstalledSize = CacheSize16;
+ Type7Record->MaximumCacheSize2 = CacheSize32;
+ Type7Record->InstalledSize2 = CacheSize32;
+
+ switch (Associativity + 1) {
+ case 2:
+ Type7Record->Associativity = CacheAssociativity2Way;
+ break;
+ case 4:
+ Type7Record->Associativity = CacheAssociativity4Way;
+ break;
+ case 8:
+ Type7Record->Associativity = CacheAssociativity8Way;
+ break;
+ case 16:
+ Type7Record->Associativity = CacheAssociativity16Way;
+ break;
+ case 12:
+ Type7Record->Associativity = CacheAssociativity12Way;
+ 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;
+ case 20:
+ Type7Record->Associativity = CacheAssociativity20Way;
+ 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;
+}
+
+
+/** Allocates and initializes an SMBIOS_TABLE_TYPE7 structure.
+
+ @param[in] CacheLevel The cache level (L1-L7).
+ @param[in] InstructionCache Cache is an instruction cache.
+ @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 InstructionCache,
+ 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,
+ InstructionCache,
+ 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 = 0; 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 > 0 && !SeparateCaches) {
+ continue;
+ }
+
+ Type7Record = AllocateAndInitCacheInformation (CacheLevel,
+ DataCacheType == 0 && SeparateCaches,
+ DataCacheType == 1,
+ DataCacheType == 0 && !SeparateCaches
+ );
+ if (Type7Record == NULL) {
+ continue;
+ }
+
+ ConfigureCacheArchitectureInformation(CacheLevel,
+ (DataCacheType == 0) && SeparateCaches,
+ DataCacheType == 1,
+ (DataCacheType == 0) && !SeparateCaches,
+ Type7Record
+ );
+
+ // Allow the platform to fill in other information such as speed, SRAM type etc.
+ if (!OemGetCacheInformation (ProcessorIndex, CacheLevel,
+ DataCacheType == 0, 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;
+}
diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorAArch64.c b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorAArch64.c
new file mode 100644
index 000000000000..96f739b2abea
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorAArch64.c
@@ -0,0 +1,97 @@
+/** @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.). Zero based.
+ @param InstructionCache Whether the cache is a dedicated instruction cache.
+ @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 InstructionCache,
+ IN BOOLEAN DataCache,
+ IN BOOLEAN UnifiedCache
+)
+{
+ CCSIDR_DATA Ccsidr;
+ CSSELR_DATA Csselr;
+ BOOLEAN CcidxSupported;
+ UINT64 CacheSize;
+
+ Csselr.Data = 0;
+ Csselr.Bits.Level = CacheLevel;
+ Csselr.Bits.InD = InstructionCache;
+
+ Ccsidr.Data = ReadCCSIDR (Csselr.Data);
+
+ CcidxSupported = ArmHasCcidx ();
+
+ if (CcidxSupported) {
+ CacheSize = (UINT64)(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.). Zero based.
+ @param InstructionCache Whether the cache is a dedicated instruction cache.
+ @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 InstructionCache,
+ IN BOOLEAN DataCache,
+ IN BOOLEAN UnifiedCache
+ )
+{
+ CCSIDR_DATA Ccsidr;
+ CSSELR_DATA Csselr;
+ BOOLEAN CcidxSupported;
+ UINT32 Associativity;
+
+ Csselr.Data = 0;
+ Csselr.Bits.Level = CacheLevel;
+ Csselr.Bits.InD = (InstructionCache | UnifiedCache);
+
+ Ccsidr.Data = ReadCCSIDR (Csselr.Data);
+
+ CcidxSupported = ArmHasCcidx ();
+
+ if (CcidxSupported) {
+ Associativity = Ccsidr.BitsCcidxAA64.Associativity;
+ } else {
+ Associativity = Ccsidr.BitsNonCcidx.Associativity;
+ }
+
+ return Associativity;
+}
+
diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArm.c b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArm.c
new file mode 100644
index 000000000000..5222b71f9f68
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArm.c
@@ -0,0 +1,103 @@
+/** @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.). Zero based.
+ @param InstructionCache Whether the cache is a dedicated instruction cache.
+ @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 InstructionCache,
+ 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;
+ Csselr.Bits.InD = (InstructionCache | UnifiedCache);
+
+ Ccsidr.Data = ReadCCSIDR (Csselr.Data);
+
+ CcidxSupported = ArmHasCcidx ();
+
+ if (CcidxSupported) {
+ Ccsidr2.Data = ReadCCSIDR2 (Csselr.Data);
+ CacheSize = (UINT64)(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.). Zero based.
+ @param InstructionCache Whether the cache is a dedicated instruction cache.
+ @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 InstructionCache,
+ 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;
+ Csselr.Bits.InD = (InstructionCache | UnifiedCache);
+
+ Ccsidr.Data = ReadCCSIDR (Csselr.Data);
+
+ CcidxSupported = ArmHasCcidx ();
+
+ if (CcidxSupported) {
+ Ccsidr2.Data = ReadCCSIDR2 (Csselr.Data);
+ Associativity = Ccsidr.BitsCcidxAA32.Associativity;
+ } else {
+ Associativity = Ccsidr.BitsNonCcidx.Associativity;
+ }
+
+ return Associativity;
+}
+
diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArmCommon.c b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArmCommon.c
new file mode 100644
index 000000000000..ed6583c19383
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/SmbiosProcessorArmCommon.c
@@ -0,0 +1,250 @@
+/** @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, 0) == 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.). Zero based.
+
+ @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);
+
+ 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;
+}
diff --git a/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni
new file mode 100644
index 000000000000..22b3c64d9fe2
--- /dev/null
+++ b/ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassStrings.uni
@@ -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"
--
2.26.2
next prev parent reply other threads:[~2021-01-31 23:25 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-31 23:24 [PATCH v7 00/21] ArmPkg,MdePkg: Add Universal/Smbios, and related changes Rebecca Cran
2021-01-31 23:24 ` [PATCH v7 01/21] ArmPkg: Add ARM SMC Architecture functions to ArmStdSmc.h Rebecca Cran
2021-01-31 23:24 ` [PATCH v7 02/21] MdePkg: Update IndustryStandard/SmBios.h with processor status data Rebecca Cran
2021-01-31 23:24 ` [PATCH v7 03/21] ArmPkg: Add register encoding definition for MMFR2 Rebecca Cran
2021-01-31 23:24 ` [PATCH v7 04/21] ArmPkg: Add helper to read the Memory Model Features Register 2 Rebecca Cran
2021-01-31 23:24 ` [PATCH v7 05/21] ArmPkg: Add helper function to read the Memory Model Feature Register 4 Rebecca Cran
2021-01-31 23:24 ` [PATCH v7 06/21] ArmPkg: Fix the return type of the ReadCCSIDR function Rebecca Cran
2021-01-31 23:24 ` [PATCH v7 07/21] ArmPkg: Update ArmLibPrivate.h with cache register definitions Rebecca Cran
2021-01-31 23:24 ` [PATCH v7 08/21] ArmPkg: Add definition of the maximum cache level in ARMv8-A Rebecca Cran
2021-01-31 23:24 ` [PATCH v7 09/21] ArmPkg: Add helper to read CCIDX status Rebecca Cran
2021-01-31 23:25 ` [PATCH v7 10/21] ArmPkg: Add helper to read the CCSIDR2 register Rebecca Cran
2021-01-31 23:25 ` [PATCH v7 11/21] ArmPkg: Add Library/OemMiscLib.h Rebecca Cran
2021-01-31 23:25 ` [PATCH v7 12/21] ArmPkg: Add Universal/Smbios/OemMiscLibNull Rebecca Cran
2021-01-31 23:25 ` Rebecca Cran [this message]
2021-02-03 15:18 ` [PATCH v7 13/21] ArmPkg: Add Universal/Smbios/ProcessorSubClassDxe Leif Lindholm
2021-02-08 14:57 ` Rebecca Cran
2021-01-31 23:25 ` [PATCH v7 14/21] ArmPkg: Add Universal/Smbios/SmbiosMiscDxe/Type00 Rebecca Cran
2021-01-31 23:25 ` [PATCH v7 15/21] ArmPkg: Add Universal/Smbios/SmbiosMiscDxe/Type01 Rebecca Cran
2021-01-31 23:25 ` [PATCH v7 16/21] ArmPkg: Add Universal/Smbios/SmbiosMiscDxe/Type02 Rebecca Cran
2021-01-31 23:25 ` [PATCH v7 17/21] ArmPkg: Add Universal/Smbios/SmbiosMiscDxe/Type03 Rebecca Cran
2021-01-31 23:25 ` [PATCH v7 18/21] ArmPkg: Add Universal/Smbios/SmbiosMiscDxe/Type13 Rebecca Cran
2021-01-31 23:25 ` [PATCH v7 19/21] ArmPkg: Add Universal/Smbios/SmbiosMiscDxe/Type32 Rebecca Cran
2021-01-31 23:25 ` [PATCH v7 20/21] ArmPkg: Add SMBIOS PCDs to ArmPkg.dec Rebecca Cran
2021-01-31 23:25 ` [PATCH v7 21/21] ArmPkg: Add Universal/Smbios/SmbiosMiscDxe Rebecca Cran
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210131232511.18340-14-rebecca@nuviainc.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox