Add UEFI application to UefiCpuPkg to display all supported CPUID
leafs and sub-leafs described by UefiCpuPkg/Include/Register/Cpuid.h
that is based on information from Intel(R) 64 and IA-32
Architectures Software Developer's Manual, Volume 2A, December
2015, CPUID instruction.

Cc: Jeff Fan <[email protected]>
Cc: Jiewen Yao <[email protected]>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Michael Kinney <[email protected]>
---
 UefiCpuPkg/Application/Cpuid/Cpuid.c        | 1353 +++++++++++++++++++++++++++
 UefiCpuPkg/Application/Cpuid/Cpuid.inf      |   48 +
 UefiCpuPkg/Application/Cpuid/Cpuid.uni      |   22 +
 UefiCpuPkg/Application/Cpuid/CpuidExtra.uni |   22 +
 UefiCpuPkg/UefiCpuPkg.dsc                   |    5 +
 5 files changed, 1450 insertions(+)
 create mode 100644 UefiCpuPkg/Application/Cpuid/Cpuid.c
 create mode 100644 UefiCpuPkg/Application/Cpuid/Cpuid.inf
 create mode 100644 UefiCpuPkg/Application/Cpuid/Cpuid.uni
 create mode 100644 UefiCpuPkg/Application/Cpuid/CpuidExtra.uni

diff --git a/UefiCpuPkg/Application/Cpuid/Cpuid.c 
b/UefiCpuPkg/Application/Cpuid/Cpuid.c
new file mode 100644
index 0000000..f82e43f
--- /dev/null
+++ b/UefiCpuPkg/Application/Cpuid/Cpuid.c
@@ -0,0 +1,1353 @@
+/** @file
+  UEFI Application to display CPUID leaf information.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Register/Cpuid.h>
+
+///
+/// Macro used to display the value of a bit field in a register returned by 
CPUID.
+///
+#define PRINT_BIT_FIELD(Variable, FieldName) \
+  Print (L"%5a%42a: %x\n", #Variable, #FieldName, ##Variable.Bits.##FieldName);
+
+///
+/// Macro used to display the value of a register returned by CPUID.
+///
+#define PRINT_VALUE(Variable, Description) \
+  Print (L"%5a%42a: %x\n", #Variable, #Description, Variable);
+
+///
+/// Structure for cache description lookup table
+///
+typedef struct {
+  UINT8  CacheDescriptor;
+  CHAR8  *Type;
+  CHAR8  *Description;
+} CPUID_CACHE_INFO_DESCRIPTION;
+
+///
+/// Cache description lookup table
+///
+CPUID_CACHE_INFO_DESCRIPTION  mCpuidCacheInfoDescription[] = {
+  { 0x00 , "General"  , "Null descriptor, this byte contains no information" },
+  { 0x01 , "TLB"      , "Instruction TLB: 4 KByte pages, 4-way set 
associative, 32 entries" },
+  { 0x02 , "TLB"      , "Instruction TLB: 4 MByte pages, fully associative, 2 
entries" },
+  { 0x03 , "TLB"      , "Data TLB: 4 KByte pages, 4-way set associative, 64 
entries" },
+  { 0x04 , "TLB"      , "Data TLB: 4 MByte pages, 4-way set associative, 8 
entries" },
+  { 0x05 , "TLB"      , "Data TLB1: 4 MByte pages, 4-way set associative, 32 
entries" },
+  { 0x06 , "Cache"    , "1st-level instruction cache: 8 KBytes, 4-way set 
associative, 32 byte line size" },
+  { 0x08 , "Cache"    , "1st-level instruction cache: 16 KBytes, 4-way set 
associative, 32 byte line size" },
+  { 0x09 , "Cache"    , "1st-level instruction cache: 32KBytes, 4-way set 
associative, 64 byte line size" },
+  { 0x0A , "Cache"    , "1st-level data cache: 8 KBytes, 2-way set 
associative, 32 byte line size" },
+  { 0x0B , "TLB"      , "Instruction TLB: 4 MByte pages, 4-way set 
associative, 4 entries" },
+  { 0x0C , "Cache"    , "1st-level data cache: 16 KBytes, 4-way set 
associative, 32 byte line size" },
+  { 0x0D , "Cache"    , "1st-level data cache: 16 KBytes, 4-way set 
associative, 64 byte line size" },
+  { 0x0E , "Cache"    , "1st-level data cache: 24 KBytes, 6-way set 
associative, 64 byte line size" },
+  { 0x1D , "Cache"    , "2nd-level cache: 128 KBytes, 2-way set associative, 
64 byte line size" },
+  { 0x21 , "Cache"    , "2nd-level cache: 256 KBytes, 8-way set associative, 
64 byte line size" },
+  { 0x22 , "Cache"    , "3rd-level cache: 512 KBytes, 4-way set associative, 
64 byte line size, 2 lines per sector" },
+  { 0x23 , "Cache"    , "3rd-level cache: 1 MBytes, 8-way set associative, 64 
byte line size, 2 lines per sector" },
+  { 0x24 , "Cache"    , "2nd-level cache: 1 MBytes, 16-way set associative, 64 
byte line size" },
+  { 0x25 , "Cache"    , "3rd-level cache: 2 MBytes, 8-way set associative, 64 
byte line size, 2 lines per sector" },
+  { 0x29 , "Cache"    , "3rd-level cache: 4 MBytes, 8-way set associative, 64 
byte line size, 2 lines per sector" },
+  { 0x2C , "Cache"    , "1st-level data cache: 32 KBytes, 8-way set 
associative, 64 byte line size" },
+  { 0x30 , "Cache"    , "1st-level instruction cache: 32 KBytes, 8-way set 
associative, 64 byte line size" },
+  { 0x40 , "Cache"    , "No 2nd-level cache or, if processor contains a valid 
2nd-level cache, no 3rd-level cache" },
+  { 0x41 , "Cache"    , "2nd-level cache: 128 KBytes, 4-way set associative, 
32 byte line size" },
+  { 0x42 , "Cache"    , "2nd-level cache: 256 KBytes, 4-way set associative, 
32 byte line size" },
+  { 0x43 , "Cache"    , "2nd-level cache: 512 KBytes, 4-way set associative, 
32 byte line size" },
+  { 0x44 , "Cache"    , "2nd-level cache: 1 MByte, 4-way set associative, 32 
byte line size" },
+  { 0x45 , "Cache"    , "2nd-level cache: 2 MByte, 4-way set associative, 32 
byte line size" },
+  { 0x46 , "Cache"    , "3rd-level cache: 4 MByte, 4-way set associative, 64 
byte line size" },
+  { 0x47 , "Cache"    , "3rd-level cache: 8 MByte, 8-way set associative, 64 
byte line size" },
+  { 0x48 , "Cache"    , "2nd-level cache: 3MByte, 12-way set associative, 64 
byte line size" },
+  { 0x49 , "Cache"    , "3rd-level cache: 4MB, 16-way set associative, 64-byte 
line size (Intel Xeon processor MP, Family 0FH, Model 06H). 2nd-level cache: 4 
MByte, 16-way set associative, 64 byte line size" },
+  { 0x4A , "Cache"    , "3rd-level cache: 6MByte, 12-way set associative, 64 
byte line size" },
+  { 0x4B , "Cache"    , "3rd-level cache: 8MByte, 16-way set associative, 64 
byte line size" },
+  { 0x4C , "Cache"    , "3rd-level cache: 12MByte, 12-way set associative, 64 
byte line size" },
+  { 0x4D , "Cache"    , "3rd-level cache: 16MByte, 16-way set associative, 64 
byte line size" },
+  { 0x4E , "Cache"    , "2nd-level cache: 6MByte, 24-way set associative, 64 
byte line size" },
+  { 0x4F , "TLB"      , "Instruction TLB: 4 KByte pages, 32 entries" },
+  { 0x50 , "TLB"      , "Instruction TLB: 4 KByte and 2-MByte or 4-MByte 
pages, 64 entries" },
+  { 0x51 , "TLB"      , "Instruction TLB: 4 KByte and 2-MByte or 4-MByte 
pages, 128 entries" },
+  { 0x52 , "TLB"      , "Instruction TLB: 4 KByte and 2-MByte or 4-MByte 
pages, 256 entries" },
+  { 0x55 , "TLB"      , "Instruction TLB: 2-MByte or 4-MByte pages, fully 
associative, 7 entries" },
+  { 0x56 , "TLB"      , "Data TLB0: 4 MByte pages, 4-way set associative, 16 
entries" },
+  { 0x57 , "TLB"      , "Data TLB0: 4 KByte pages, 4-way associative, 16 
entries" },
+  { 0x59 , "TLB"      , "Data TLB0: 4 KByte pages, fully associative, 16 
entries" },
+  { 0x5A , "TLB"      , "Data TLB0: 2-MByte or 4 MByte pages, 4-way set 
associative, 32 entries" },
+  { 0x5B , "TLB"      , "Data TLB: 4 KByte and 4 MByte pages, 64 entries" },
+  { 0x5C , "TLB"      , "Data TLB: 4 KByte and 4 MByte pages,128 entries" },
+  { 0x5D , "TLB"      , "Data TLB: 4 KByte and 4 MByte pages,256 entries" },
+  { 0x60 , "Cache"    , "1st-level data cache: 16 KByte, 8-way set 
associative, 64 byte line size" },
+  { 0x61 , "TLB"      , "Instruction TLB: 4 KByte pages, fully associative, 48 
entries" },
+  { 0x63 , "TLB"      , "Data TLB: 1 GByte pages, 4-way set associative, 4 
entries" },
+  { 0x66 , "Cache"    , "1st-level data cache: 8 KByte, 4-way set associative, 
64 byte line size" },
+  { 0x67 , "Cache"    , "1st-level data cache: 16 KByte, 4-way set 
associative, 64 byte line size" },
+  { 0x68 , "Cache"    , "1st-level data cache: 32 KByte, 4-way set 
associative, 64 byte line size" },
+  { 0x6A , "Cache"    , "uTLB: 4 KByte pages, 8-way set associative, 64 
entries" },
+  { 0x6B , "Cache"    , "DTLB: 4 KByte pages, 8-way set associative, 256 
entries" },
+  { 0x6C , "Cache"    , "DTLB: 2M/4M pages, 8-way set associative, 128 
entries" },
+  { 0x6D , "Cache"    , "DTLB: 1 GByte pages, fully associative, 16 entries" },
+  { 0x70 , "Cache"    , "Trace cache: 12 K-uop, 8-way set associative" },
+  { 0x71 , "Cache"    , "Trace cache: 16 K-uop, 8-way set associative" },
+  { 0x72 , "Cache"    , "Trace cache: 32 K-uop, 8-way set associative" },
+  { 0x76 , "TLB"      , "Instruction TLB: 2M/4M pages, fully associative, 8 
entries" },
+  { 0x78 , "Cache"    , "2nd-level cache: 1 MByte, 4-way set associative, 
64byte line size" },
+  { 0x79 , "Cache"    , "2nd-level cache: 128 KByte, 8-way set associative, 64 
byte line size, 2 lines per sector" },
+  { 0x7A , "Cache"    , "2nd-level cache: 256 KByte, 8-way set associative, 64 
byte line size, 2 lines per sector" },
+  { 0x7B , "Cache"    , "2nd-level cache: 512 KByte, 8-way set associative, 64 
byte line size, 2 lines per sector" },
+  { 0x7C , "Cache"    , "2nd-level cache: 1 MByte, 8-way set associative, 64 
byte line size, 2 lines per sector" },
+  { 0x7D , "Cache"    , "2nd-level cache: 2 MByte, 8-way set associative, 
64byte line size" },
+  { 0x7F , "Cache"    , "2nd-level cache: 512 KByte, 2-way set associative, 
64-byte line size" },
+  { 0x80 , "Cache"    , "2nd-level cache: 512 KByte, 8-way set associative, 
64-byte line size" },
+  { 0x82 , "Cache"    , "2nd-level cache: 256 KByte, 8-way set associative, 32 
byte line size" },
+  { 0x83 , "Cache"    , "2nd-level cache: 512 KByte, 8-way set associative, 32 
byte line size" },
+  { 0x84 , "Cache"    , "2nd-level cache: 1 MByte, 8-way set associative, 32 
byte line size" },
+  { 0x85 , "Cache"    , "2nd-level cache: 2 MByte, 8-way set associative, 32 
byte line size" },
+  { 0x86 , "Cache"    , "2nd-level cache: 512 KByte, 4-way set associative, 64 
byte line size" },
+  { 0x87 , "Cache"    , "2nd-level cache: 1 MByte, 8-way set associative, 64 
byte line size" },
+  { 0xA0 , "DTLB"     , "DTLB: 4k pages, fully associative, 32 entries" },
+  { 0xB0 , "TLB"      , "Instruction TLB: 4 KByte pages, 4-way set 
associative, 128 entries" },
+  { 0xB1 , "TLB"      , "Instruction TLB: 2M pages, 4-way, 8 entries or 4M 
pages, 4-way, 4 entries" },
+  { 0xB2 , "TLB"      , "Instruction TLB: 4KByte pages, 4-way set associative, 
64 entries" },
+  { 0xB3 , "TLB"      , "Data TLB: 4 KByte pages, 4-way set associative, 128 
entries" },
+  { 0xB4 , "TLB"      , "Data TLB1: 4 KByte pages, 4-way associative, 256 
entries" },
+  { 0xB5 , "TLB"      , "Instruction TLB: 4KByte pages, 8-way set associative, 
64 entries" },
+  { 0xB6 , "TLB"      , "Instruction TLB: 4KByte pages, 8-way set associative, 
128 entries" },
+  { 0xBA , "TLB"      , "Data TLB1: 4 KByte pages, 4-way associative, 64 
entries" },
+  { 0xC0 , "TLB"      , "Data TLB: 4 KByte and 4 MByte pages, 4-way 
associative, 8 entries" },
+  { 0xC1 , "STLB"     , "Shared 2nd-Level TLB: 4 KByte/2MByte pages, 8-way 
associative, 1024 entries" },
+  { 0xC2 , "DTLB"     , "DTLB: 4 KByte/2 MByte pages, 4-way associative, 16 
entries" },
+  { 0xC3 , "STLB"     , "Shared 2nd-Level TLB: 4 KByte /2 MByte pages, 6-way 
associative, 1536 entries. Also 1GBbyte pages, 4-way, 16 entries." },
+  { 0xCA , "STLB"     , "Shared 2nd-Level TLB: 4 KByte pages, 4-way 
associative, 512 entries" },
+  { 0xD0 , "Cache"    , "3rd-level cache: 512 KByte, 4-way set associative, 64 
byte line size" },
+  { 0xD1 , "Cache"    , "3rd-level cache: 1 MByte, 4-way set associative, 64 
byte line size" },
+  { 0xD2 , "Cache"    , "3rd-level cache: 2 MByte, 4-way set associative, 64 
byte line size" },
+  { 0xD6 , "Cache"    , "3rd-level cache: 1 MByte, 8-way set associative, 64 
byte line size" },
+  { 0xD7 , "Cache"    , "3rd-level cache: 2 MByte, 8-way set associative, 64 
byte line size" },
+  { 0xD8 , "Cache"    , "3rd-level cache: 4 MByte, 8-way set associative, 64 
byte line size" },
+  { 0xDC , "Cache"    , "3rd-level cache: 1.5 MByte, 12-way set associative, 
64 byte line size" },
+  { 0xDD , "Cache"    , "3rd-level cache: 3 MByte, 12-way set associative, 64 
byte line size" },
+  { 0xDE , "Cache"    , "3rd-level cache: 6 MByte, 12-way set associative, 64 
byte line size" },
+  { 0xE2 , "Cache"    , "3rd-level cache: 2 MByte, 16-way set associative, 64 
byte line size" },
+  { 0xE3 , "Cache"    , "3rd-level cache: 4 MByte, 16-way set associative, 64 
byte line size" },
+  { 0xE4 , "Cache"    , "3rd-level cache: 8 MByte, 16-way set associative, 64 
byte line size" },
+  { 0xEA , "Cache"    , "3rd-level cache: 12MByte, 24-way set associative, 64 
byte line size" },
+  { 0xEB , "Cache"    , "3rd-level cache: 18MByte, 24-way set associative, 64 
byte line size" },
+  { 0xEC , "Cache"    , "3rd-level cache: 24MByte, 24-way set associative, 64 
byte line size" },
+  { 0xF0 , "Prefetch" , "64-Byte prefetching" },
+  { 0xF1 , "Prefetch" , "128-Byte prefetching" },
+  { 0xFF , "General"  , "CPUID leaf 2 does not report cache descriptor 
information, use CPUID leaf 4 to query cache parameters" }
+};
+
+///
+/// The maximum supported CPUID leaf index starting from leaf 0x00000000.
+///
+UINT32  gMaximumBasicFunction    = CPUID_SIGNATURE;
+
+///
+/// The maximum supported CPUID leaf index starting from leaf 0x80000000.
+///
+UINT32  gMaximumExtendedFunction = CPUID_EXTENDED_FUNCTION;
+
+/**
+  Display CPUID_SIGNATURE leaf.
+
+**/
+VOID
+CpuidSignature (
+  VOID
+  )
+{
+  UINT32 Eax;
+  UINT32 Ebx;
+  UINT32 Ecx;
+  UINT32 Edx;
+  CHAR8  Signature[13];
+
+  if (CPUID_SIGNATURE > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_SIGNATURE, &Eax, &Ebx, &Ecx, &Edx);
+
+  Print (L"CPUID_SIGNATURE (Leaf %08x)\n", CPUID_SIGNATURE);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, Ebx, Ecx, Edx);
+  PRINT_VALUE (Eax, MaximumLeaf);
+  *(UINT32 *)(Signature + 0) = Ebx;
+  *(UINT32 *)(Signature + 4) = Edx;
+  *(UINT32 *)(Signature + 8) = Ecx;
+  Signature [12] = 0;
+  Print (L"  Signature = %a\n", Signature);
+
+  gMaximumBasicFunction = Eax;
+}
+
+/**
+  Display CPUID_VERSION_INFO leaf.
+
+**/
+VOID
+CpuidVersionInfo (
+  VOID
+  )
+{
+  CPUID_VERSION_INFO_EAX  Eax;
+  CPUID_VERSION_INFO_EBX  Ebx;
+  CPUID_VERSION_INFO_ECX  Ecx;
+  CPUID_VERSION_INFO_EDX  Edx;
+  UINTN                   DisplayFamily;
+  UINTN                   DisplayModel;
+
+  if (CPUID_VERSION_INFO > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, 
&Edx.Uint32);
+
+  Print (L"CPUID_VERSION_INFO (Leaf %08x)\n", CPUID_VERSION_INFO);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+
+  DisplayFamily = Eax.Bits.FamilyId;
+  if (Eax.Bits.FamilyId == 0x0F) {
+    DisplayFamily |= (Eax.Bits.ExtendedFamilyId << 4);
+  }
+
+  DisplayModel = Eax.Bits.Model;
+  if (Eax.Bits.FamilyId == 0x06 || Eax.Bits.FamilyId == 0x0f) {
+    DisplayModel |= (Eax.Bits.ExtendedModelId << 4);
+  }
+
+  Print (L"  Family = %x  Model = %x  Stepping = %x\n", DisplayFamily, 
DisplayModel, Eax.Bits.SteppingId);
+
+  PRINT_BIT_FIELD (Eax, SteppingId);
+  PRINT_BIT_FIELD (Eax, Model);
+  PRINT_BIT_FIELD (Eax, FamilyId);
+  PRINT_BIT_FIELD (Eax, ProcessorType);
+  PRINT_BIT_FIELD (Eax, ExtendedModelId);
+  PRINT_BIT_FIELD (Eax, ExtendedFamilyId);
+  PRINT_BIT_FIELD (Ebx, BrandIndex);
+  PRINT_BIT_FIELD (Ebx, CacheLineSize);
+  PRINT_BIT_FIELD (Ebx, MaximumAddressableIdsForLogicalProcessors);
+  PRINT_BIT_FIELD (Ebx, InitialLocalApicId);
+  PRINT_BIT_FIELD (Ecx, SSE3);
+  PRINT_BIT_FIELD (Ecx, PCLMULQDQ);
+  PRINT_BIT_FIELD (Ecx, DTES64);
+  PRINT_BIT_FIELD (Ecx, MONITOR);
+  PRINT_BIT_FIELD (Ecx, DS_CPL);
+  PRINT_BIT_FIELD (Ecx, VMX);
+  PRINT_BIT_FIELD (Ecx, SMX);
+  PRINT_BIT_FIELD (Ecx, TM2);
+  PRINT_BIT_FIELD (Ecx, SSSE3);
+  PRINT_BIT_FIELD (Ecx, CNXT_ID);
+  PRINT_BIT_FIELD (Ecx, SDBG);
+  PRINT_BIT_FIELD (Ecx, FMA);
+  PRINT_BIT_FIELD (Ecx, CMPXCHG16B);
+  PRINT_BIT_FIELD (Ecx, xTPR_Update_Control);
+  PRINT_BIT_FIELD (Ecx, PDCM);
+  PRINT_BIT_FIELD (Ecx, PCID);
+  PRINT_BIT_FIELD (Ecx, DCA);
+  PRINT_BIT_FIELD (Ecx, SSE4_1);
+  PRINT_BIT_FIELD (Ecx, SSE4_2);
+  PRINT_BIT_FIELD (Ecx, x2APIC);
+  PRINT_BIT_FIELD (Ecx, MOVBE);
+  PRINT_BIT_FIELD (Ecx, POPCNT);
+  PRINT_BIT_FIELD (Ecx, TSC_Deadline);
+  PRINT_BIT_FIELD (Ecx, AESNI);
+  PRINT_BIT_FIELD (Ecx, XSAVE);
+  PRINT_BIT_FIELD (Ecx, OSXSAVE);
+  PRINT_BIT_FIELD (Ecx, AVX);
+  PRINT_BIT_FIELD (Ecx, F16C);
+  PRINT_BIT_FIELD (Ecx, RDRAND);
+  PRINT_BIT_FIELD (Edx, FPU);
+  PRINT_BIT_FIELD (Edx, VME);
+  PRINT_BIT_FIELD (Edx, DE);
+  PRINT_BIT_FIELD (Edx, PSE);
+  PRINT_BIT_FIELD (Edx, TSC);
+  PRINT_BIT_FIELD (Edx, MSR);
+  PRINT_BIT_FIELD (Edx, PAE);
+  PRINT_BIT_FIELD (Edx, MCE);
+  PRINT_BIT_FIELD (Edx, CX8);
+  PRINT_BIT_FIELD (Edx, APIC);
+  PRINT_BIT_FIELD (Edx, SEP);
+  PRINT_BIT_FIELD (Edx, MTRR);
+  PRINT_BIT_FIELD (Edx, PGE);
+  PRINT_BIT_FIELD (Edx, MCA);
+  PRINT_BIT_FIELD (Edx, CMOV);
+  PRINT_BIT_FIELD (Edx, PAT);
+  PRINT_BIT_FIELD (Edx, PSE_36);
+  PRINT_BIT_FIELD (Edx, PSN);
+  PRINT_BIT_FIELD (Edx, CLFSH);
+  PRINT_BIT_FIELD (Edx, DS);
+  PRINT_BIT_FIELD (Edx, ACPI);
+  PRINT_BIT_FIELD (Edx, MMX);
+  PRINT_BIT_FIELD (Edx, FXSR);
+  PRINT_BIT_FIELD (Edx, SSE);
+  PRINT_BIT_FIELD (Edx, SSE2);
+  PRINT_BIT_FIELD (Edx, SS);
+  PRINT_BIT_FIELD (Edx, HTT);
+  PRINT_BIT_FIELD (Edx, TM);
+  PRINT_BIT_FIELD (Edx, PBE);
+}
+
+/**
+  Lookup a cache description string from the mCpuidCacheInfoDescription table.
+
+  @param[in] CacheDescriptor  Cache descriptor value from CPUID_CACHE_INFO.
+
+**/
+CPUID_CACHE_INFO_DESCRIPTION *
+LookupCacheDescription (
+  UINT8  CacheDescriptor
+  )
+{
+  UINTN  NumDescriptors;
+  UINTN  Descriptor;
+
+  if (CacheDescriptor == 0x00) {
+    return NULL;
+  }
+  NumDescriptors = sizeof (mCpuidCacheInfoDescription)/sizeof 
(mCpuidCacheInfoDescription[0]);
+  for (Descriptor = 0; Descriptor < NumDescriptors; Descriptor++) {
+    if (CacheDescriptor == 
mCpuidCacheInfoDescription[Descriptor].CacheDescriptor) {
+      return &mCpuidCacheInfoDescription[Descriptor];
+    }
+  }
+  return NULL;
+}
+
+/**
+  Display CPUID_CACHE_INFO leaf for each supported cache descriptor.
+
+**/
+VOID
+CpuidCacheInfo (
+  VOID
+  )
+{
+  CPUID_CACHE_INFO_CACHE_TLB    Eax;
+  CPUID_CACHE_INFO_CACHE_TLB    Ebx;
+  CPUID_CACHE_INFO_CACHE_TLB    Ecx;
+  CPUID_CACHE_INFO_CACHE_TLB    Edx;
+  UINTN                         Index;
+  CPUID_CACHE_INFO_DESCRIPTION  *CacheDescription;
+
+  if (CPUID_CACHE_INFO > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_CACHE_INFO, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, 
&Edx.Uint32);
+
+  Print (L"CPUID_CACHE_INFO (Leaf %08x)\n", CPUID_CACHE_INFO);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+  if (Eax.Bits.NotValid == 0) {
+    //
+    // Process Eax.CacheDescriptor[1..3].  Ignore Eax.CacheDescriptor[0]
+    //
+    for (Index = 1; Index < 4; Index++) {
+      CacheDescription = LookupCacheDescription (Eax.CacheDescriptor[Index]);
+      if (CacheDescription != NULL) {
+        Print (L"  %-8a %a\n",
+          CacheDescription->Type,
+          CacheDescription->Description
+          );
+      }
+    }
+  }
+  if (Ebx.Bits.NotValid == 0) {
+    //
+    // Process Ebx.CacheDescriptor[0..3]
+    //
+    for (Index = 0; Index < 4; Index++) {
+      CacheDescription = LookupCacheDescription (Ebx.CacheDescriptor[Index]);
+      if (CacheDescription != NULL) {
+        Print (L"  %-8a %a\n",
+          CacheDescription->Type,
+          CacheDescription->Description
+          );
+      }
+    }
+  }
+  if (Ecx.Bits.NotValid == 0) {
+    //
+    // Process Ecx.CacheDescriptor[0..3]
+    //
+    for (Index = 0; Index < 4; Index++) {
+      CacheDescription = LookupCacheDescription (Ecx.CacheDescriptor[Index]);
+      if (CacheDescription != NULL) {
+        Print (L"  %-8a %a\n",
+          CacheDescription->Type,
+          CacheDescription->Description
+          );
+      }
+    }
+  }
+  if (Edx.Bits.NotValid == 0) {
+    //
+    // Process Edx.CacheDescriptor[0..3]
+    //
+    for (Index = 0; Index < 4; Index++) {
+      CacheDescription = LookupCacheDescription (Edx.CacheDescriptor[Index]);
+      if (CacheDescription != NULL) {
+        Print (L"  %-8a %a\n",
+          CacheDescription->Type,
+          CacheDescription->Description
+          );
+      }
+    }
+  }
+}
+
+/**
+  Display CPUID_SERIAL_NUMBER leaf if it is supported.
+
+**/
+VOID
+CpuidSerialNumber (
+  VOID
+  )
+{
+  CPUID_VERSION_INFO_EDX  VersionInfoEdx;
+  UINT32                  Ecx;
+  UINT32                  Edx;
+
+  Print (L"CPUID_SERIAL_NUMBER (Leaf %08x)\n", CPUID_SERIAL_NUMBER);
+
+  if (CPUID_SERIAL_NUMBER > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &VersionInfoEdx.Uint32);
+  if (VersionInfoEdx.Bits.PSN == 0) {
+    Print (L"  Not Supported\n");
+    return;
+  }
+
+  AsmCpuid (CPUID_SERIAL_NUMBER, NULL, NULL, &Ecx, &Edx);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", 0, 0, Ecx, Edx);
+  Print (L"  Processor Serial Number = %08x%08x%08x\n", 0, Edx, Ecx);
+}
+
+/**
+  Display CPUID_CACHE_PARAMS for all supported sub-leafs.
+
+**/
+VOID
+CpuidCacheParams (
+  VOID
+  )
+{
+  UINT32                  CacheLevel;
+  CPUID_CACHE_PARAMS_EAX  Eax;
+  CPUID_CACHE_PARAMS_EBX  Ebx;
+  UINT32                  Ecx;
+  CPUID_CACHE_PARAMS_EDX  Edx;
+
+  if (CPUID_CACHE_PARAMS > gMaximumBasicFunction) {
+    return;
+  }
+
+  CacheLevel = 0;
+  do {
+    AsmCpuidEx (
+      CPUID_CACHE_PARAMS, CacheLevel,
+      &Eax.Uint32, &Ebx.Uint32, &Ecx, &Edx.Uint32
+      );
+    if (Eax.Bits.CacheType != CPUID_CACHE_PARAMS_CACHE_TYPE_NULL) {
+      Print (L"CPUID_CACHE_PARAMS (Leaf %08x, Sub-Leaf %08x)\n", 
CPUID_CACHE_PARAMS, CacheLevel);
+      Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, Ecx, Edx.Uint32);
+      PRINT_BIT_FIELD (Eax, CacheType);
+      PRINT_BIT_FIELD (Eax, CacheLevel);
+      PRINT_BIT_FIELD (Eax, SelfInitializingCache);
+      PRINT_BIT_FIELD (Eax, FullyAssociativeCache);
+      PRINT_BIT_FIELD (Eax, MaximumAddressableIdsForLogicalProcessors);
+      PRINT_BIT_FIELD (Eax, MaximumAddressableIdsForProcessorCores);
+      PRINT_BIT_FIELD (Ebx, LineSize);
+      PRINT_BIT_FIELD (Ebx, LinePartitions);
+      PRINT_BIT_FIELD (Ebx, Ways);
+      PRINT_VALUE     (Ecx, NumberOfSets);
+      PRINT_BIT_FIELD (Edx, Invalidate);
+      PRINT_BIT_FIELD (Edx, CacheInclusiveness);
+      PRINT_BIT_FIELD (Edx, ComplexCacheIndexing);
+    }
+    CacheLevel++;
+  } while (Eax.Bits.CacheType != CPUID_CACHE_PARAMS_CACHE_TYPE_NULL);
+}
+
+/**
+  Display CPUID_MONITOR_MWAIT leaf.
+
+**/
+VOID
+CpuidMonitorMwait (
+  VOID
+  )
+{
+  CPUID_MONITOR_MWAIT_EAX  Eax;
+  CPUID_MONITOR_MWAIT_EBX  Ebx;
+  CPUID_MONITOR_MWAIT_ECX  Ecx;
+  CPUID_MONITOR_MWAIT_EDX  Edx;
+
+  if (CPUID_MONITOR_MWAIT > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_MONITOR_MWAIT, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, 
&Edx.Uint32);
+
+  Print (L"CPUID_MONITOR_MWAIT (Leaf %08x)\n", CPUID_MONITOR_MWAIT);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+
+  PRINT_BIT_FIELD (Eax, SmallestMonitorLineSize);
+  PRINT_BIT_FIELD (Ebx, LargestMonitorLineSize);
+  PRINT_BIT_FIELD (Ecx, ExtensionsSupported);
+  PRINT_BIT_FIELD (Ecx, InterruptAsBreak);
+  PRINT_BIT_FIELD (Edx, C0States);
+  PRINT_BIT_FIELD (Edx, C1States);
+  PRINT_BIT_FIELD (Edx, C2States);
+  PRINT_BIT_FIELD (Edx, C3States);
+  PRINT_BIT_FIELD (Edx, C4States);
+  PRINT_BIT_FIELD (Edx, C5States);
+  PRINT_BIT_FIELD (Edx, C6States);
+  PRINT_BIT_FIELD (Edx, C7States);
+}
+
+/**
+  Display CPUID_THERMAL_POWER_MANAGEMENT leaf.
+
+**/
+VOID
+CpuidThermalPowerManagement (
+  VOID
+  )
+{
+  CPUID_THERMAL_POWER_MANAGEMENT_EAX  Eax;
+  CPUID_THERMAL_POWER_MANAGEMENT_EBX  Ebx;
+  CPUID_THERMAL_POWER_MANAGEMENT_ECX  Ecx;
+
+  if (CPUID_THERMAL_POWER_MANAGEMENT > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_THERMAL_POWER_MANAGEMENT, &Eax.Uint32, &Ebx.Uint32, 
&Ecx.Uint32, NULL);
+
+  Print (L"CPUID_THERMAL_POWER_MANAGEMENT (Leaf %08x)\n", 
CPUID_THERMAL_POWER_MANAGEMENT);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, Ecx.Uint32, 0);
+
+  PRINT_BIT_FIELD (Eax, DigitalTemperatureSensor);
+  PRINT_BIT_FIELD (Eax, TurboBoostTechnology);
+  PRINT_BIT_FIELD (Eax, ARAT);
+  PRINT_BIT_FIELD (Eax, PLN);
+  PRINT_BIT_FIELD (Eax, ECMD);
+  PRINT_BIT_FIELD (Eax, PTM);
+  PRINT_BIT_FIELD (Eax, HWP);
+  PRINT_BIT_FIELD (Eax, HWP_Notification);
+  PRINT_BIT_FIELD (Eax, HWP_Activity_Window);
+  PRINT_BIT_FIELD (Eax, HWP_Energy_Performance_Preference);
+  PRINT_BIT_FIELD (Eax, HWP_Package_Level_Request);
+  PRINT_BIT_FIELD (Eax, HDC);
+  PRINT_BIT_FIELD (Ebx, InterruptThresholds);
+  PRINT_BIT_FIELD (Ecx, HardwareCoordinationFeedback);
+  PRINT_BIT_FIELD (Ecx, PerformanceEnergyBias);
+}
+
+/**
+  Display CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS for all supported sub-leafs.
+
+**/
+VOID
+CpuidStructuredExtendedFeatureFlags (
+  VOID
+  )
+{
+  UINT32                                       Eax;
+  CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_EBX  Ebx;
+  CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX  Ecx;
+  UINT32                                       SubLeaf;
+
+  if (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuidEx (
+    CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
+    CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO,
+    &Eax, NULL, NULL, NULL
+    );
+  for (SubLeaf = 0; SubLeaf <= Eax; SubLeaf++) {
+    AsmCpuidEx (
+      CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
+      SubLeaf,
+      NULL, &Ebx.Uint32, &Ecx.Uint32, NULL
+      );
+    if (Ebx.Uint32 != 0 || Ecx.Uint32 != 0) {
+      Print (L"CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS (Leaf %08x, Sub-Leaf 
%08x)\n", CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, SubLeaf);
+      Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, Ebx.Uint32, 
Ecx.Uint32, 0);
+      PRINT_BIT_FIELD (Ebx, FSGSBASE);
+      PRINT_BIT_FIELD (Ebx, IA32_TSC_ADJUST);
+      PRINT_BIT_FIELD (Ebx, BMI1);
+      PRINT_BIT_FIELD (Ebx, HLE);
+      PRINT_BIT_FIELD (Ebx, AVX2);
+      PRINT_BIT_FIELD (Ebx, FDP_EXCPTN_ONLY);
+      PRINT_BIT_FIELD (Ebx, SMEP);
+      PRINT_BIT_FIELD (Ebx, BMI2);
+      PRINT_BIT_FIELD (Ebx, EnhancedRepMovsbStosb);
+      PRINT_BIT_FIELD (Ebx, INVPCID);
+      PRINT_BIT_FIELD (Ebx, RTM);
+      PRINT_BIT_FIELD (Ebx, PQM);
+      PRINT_BIT_FIELD (Ebx, DeprecateFpuCsDs);
+      PRINT_BIT_FIELD (Ebx, MPX);
+      PRINT_BIT_FIELD (Ebx, PQE);
+      PRINT_BIT_FIELD (Ebx, RDSEED);
+      PRINT_BIT_FIELD (Ebx, ADX);
+      PRINT_BIT_FIELD (Ebx, SMAP);
+      PRINT_BIT_FIELD (Ebx, CLFLUSHOPT);
+      PRINT_BIT_FIELD (Ebx, IntelProcessorTrace);
+      PRINT_BIT_FIELD (Ecx, PREFETCHWT1);
+      PRINT_BIT_FIELD (Ecx, PKU);
+      PRINT_BIT_FIELD (Ecx, OSPKE);
+    }
+    SubLeaf++;
+  } while (SubLeaf <= Eax);
+}
+
+/**
+  Display CPUID_DIRECT_CACHE_ACCESS_INFO leaf.
+
+**/
+VOID
+CpuidDirectCacheAccessInfo (
+  VOID
+  )
+{
+  UINT32  Eax;
+
+  if (CPUID_DIRECT_CACHE_ACCESS_INFO > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_DIRECT_CACHE_ACCESS_INFO, &Eax, NULL, NULL, NULL);
+  Print (L"CPUID_DIRECT_CACHE_ACCESS_INFO (Leaf %08x)\n", 
CPUID_DIRECT_CACHE_ACCESS_INFO);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, 0, 0, 0);
+}
+
+/**
+  Display CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING leaf.
+
+**/
+VOID
+CpuidArchitecturalPerformanceMonitoring (
+  VOID
+  )
+{
+  CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING_EAX  Eax;
+  CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING_EBX  Ebx;
+  CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING_EDX  Edx;
+
+  if (CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING, &Eax.Uint32, 
&Ebx.Uint32, NULL, &Edx.Uint32);
+  Print (L"CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING (Leaf %08x)\n", 
CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, 0, Edx.Uint32);
+  PRINT_BIT_FIELD (Eax, ArchPerfMonVerID);
+  PRINT_BIT_FIELD (Eax, PerformanceMonitorCounters);
+  PRINT_BIT_FIELD (Eax, PerformanceMonitorCounterWidth);
+  PRINT_BIT_FIELD (Eax, EbxBitVectorLength);
+  PRINT_BIT_FIELD (Ebx, UnhaltedCoreCycles);
+  PRINT_BIT_FIELD (Ebx, InstructionsRetired);
+  PRINT_BIT_FIELD (Ebx, UnhaltedReferenceCycles);
+  PRINT_BIT_FIELD (Ebx, LastLevelCacheReferences);
+  PRINT_BIT_FIELD (Ebx, LastLevelCacheMisses);
+  PRINT_BIT_FIELD (Ebx, BranchInstructionsRetired);
+  PRINT_BIT_FIELD (Ebx, AllBranchMispredictRetired);
+  PRINT_BIT_FIELD (Edx, FixedFunctionPerformanceCounters);
+  PRINT_BIT_FIELD (Edx, FixedFunctionPerformanceCounterWidth);
+}
+
+/**
+  Display CPUID_EXTENDED_TOPOLOGY leafs for all supported levels.
+
+**/
+VOID
+CpuidExtendedTopology (
+  VOID
+  )
+{
+  CPUID_EXTENDED_TOPOLOGY_EAX  Eax;
+  CPUID_EXTENDED_TOPOLOGY_EBX  Ebx;
+  CPUID_EXTENDED_TOPOLOGY_ECX  Ecx;
+  UINT32                       Edx;
+  UINT32                       LevelNumber;
+
+  if (CPUID_EXTENDED_TOPOLOGY > gMaximumBasicFunction) {
+    return;
+  }
+
+  LevelNumber = 0;
+  do {
+    AsmCpuidEx (
+      CPUID_EXTENDED_TOPOLOGY, LevelNumber,
+      &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx
+      );
+    if (Eax.Bits.ApicIdShift != 0) {
+      Print (L"CPUID_EXTENDED_TOPOLOGY (Leaf %08x, Sub-Leaf %08x)\n", 
CPUID_EXTENDED_TOPOLOGY, LevelNumber);
+      Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, Ecx.Uint32, Edx);
+      PRINT_BIT_FIELD (Eax, ApicIdShift);
+      PRINT_BIT_FIELD (Ebx, LogicalProcessors);
+      PRINT_BIT_FIELD (Ecx, LevelNumber);
+      PRINT_BIT_FIELD (Ecx, LevelType);
+      PRINT_VALUE     (Edx, x2APIC_ID);
+    }
+    LevelNumber++;
+  } while (Eax.Bits.ApicIdShift != 0);
+}
+
+/**
+  Display CPUID_EXTENDED_STATE sub-leaf.
+
+**/
+VOID
+CpuidExtendedStateSubLeaf (
+  VOID
+  )
+{
+  CPUID_EXTENDED_STATE_SUB_LEAF_EAX  Eax;
+  UINT32                             Ebx;
+  CPUID_EXTENDED_STATE_SUB_LEAF_ECX  Ecx;
+  UINT32                             Edx;
+
+  AsmCpuidEx (
+    CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_SUB_LEAF,
+    &Eax.Uint32, &Ebx, &Ecx.Uint32, &Edx
+    );
+  Print (L"CPUID_EXTENDED_STATE (Leaf %08x, Sub-Leaf %08x)\n", 
CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_SUB_LEAF);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx, 
Ecx.Uint32, Edx);
+  PRINT_BIT_FIELD (Eax, XSAVEOPT);
+  PRINT_BIT_FIELD (Eax, XSAVEC);
+  PRINT_BIT_FIELD (Eax, XGETBV);
+  PRINT_BIT_FIELD (Eax, XSAVES);
+  PRINT_VALUE     (Ebx, EnabledSaveStateSize_XCR0_IA32_XSS);
+  PRINT_BIT_FIELD (Ecx, XCR0);
+  PRINT_BIT_FIELD (Ecx, PT);
+  PRINT_BIT_FIELD (Ecx, XCR0_1);
+  PRINT_VALUE     (Edx, IA32_XSS_Supported_32_63);
+}
+
+/**
+  Display CPUID_EXTENDED_STATE size and offset information sub-leaf.
+
+**/
+VOID
+CpuidExtendedStateSizeOffset (
+  VOID
+  )
+{
+  UINT32                                Eax;
+  UINT32                                Ebx;
+  CPUID_EXTENDED_STATE_SIZE_OFFSET_ECX  Ecx;
+  UINT32                                Edx;
+  UINT32                                SubLeaf;
+
+  for (SubLeaf = CPUID_EXTENDED_STATE_SIZE_OFFSET; SubLeaf < 32; SubLeaf++) {
+    AsmCpuidEx (
+      CPUID_EXTENDED_STATE, SubLeaf,
+      &Eax, &Ebx, &Ecx.Uint32, &Edx
+      );
+    if (Edx != 0) {
+      Print (L"CPUID_EXTENDED_STATE (Leaf %08x, Sub-Leaf %08x)\n", 
CPUID_EXTENDED_STATE, SubLeaf);
+      Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, Ebx, 
Ecx.Uint32, Edx);
+      PRINT_VALUE     (Eax, FeatureSaveStateSize);
+      PRINT_VALUE     (Ebx, FeatureSaveStateOffset);
+      PRINT_BIT_FIELD (Ecx, XSS);
+      PRINT_BIT_FIELD (Ecx, Compacted);
+    }
+  }
+}
+
+/**
+  Display CPUID_EXTENDED_STATE main leaf and sub-leafs.
+
+**/
+VOID
+CpuidExtendedStateMainLeaf (
+  VOID
+  )
+{
+  CPUID_EXTENDED_STATE_MAIN_LEAF_EAX  Eax;
+  UINT32                              Ebx;
+  UINT32                              Ecx;
+  UINT32                              Edx;
+
+  if (CPUID_EXTENDED_STATE > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuidEx (
+    CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_MAIN_LEAF,
+    &Eax.Uint32, &Ebx, &Ecx, &Edx
+    );
+  Print (L"CPUID_EXTENDED_STATE (Leaf %08x, Sub-Leaf %08x)\n", 
CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_MAIN_LEAF);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx, Ecx, 
Edx);
+  PRINT_BIT_FIELD (Eax, x87);
+  PRINT_BIT_FIELD (Eax, SSE);
+  PRINT_BIT_FIELD (Eax, AVX);
+  PRINT_BIT_FIELD (Eax, MPX);
+  PRINT_BIT_FIELD (Eax, AVX_512);
+  PRINT_BIT_FIELD (Eax, IA32_XSS);
+  PRINT_BIT_FIELD (Eax, PKRU);
+  PRINT_VALUE     (Ebx, EnabledSaveStateSize);
+  PRINT_VALUE     (Ecx, SupportedSaveStateSize);
+  PRINT_VALUE     (Edx, XCR0_Supported_32_63);
+
+  CpuidExtendedStateSubLeaf ();
+  CpuidExtendedStateSizeOffset ();
+}
+
+/**
+  Display CPUID_PLATFORM_QOS_MONITORING enumeration sub-leaf.
+
+**/
+VOID
+CpuidPlatformQosMonitoringEnumerationSubLeaf (
+  VOID
+  )
+{
+  UINT32                                                  Ebx;
+  CPUID_PLATFORM_QOS_MONITORING_ENUMERATION_SUB_LEAF_EDX  Edx;
+
+  if (CPUID_PLATFORM_QOS_MONITORING > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuidEx (
+    CPUID_PLATFORM_QOS_MONITORING, 
CPUID_PLATFORM_QOS_MONITORING_ENUMERATION_SUB_LEAF,
+    NULL, &Ebx, NULL, &Edx.Uint32
+    );
+  Print (L"CPUID_PLATFORM_QOS_MONITORING (Leaf %08x, Sub-Leaf %08x)\n", 
CPUID_PLATFORM_QOS_MONITORING, 
CPUID_PLATFORM_QOS_MONITORING_ENUMERATION_SUB_LEAF);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", 0, Ebx, 0, Edx.Uint32);
+  PRINT_VALUE     (Ebx, Maximum_RMID_Range);
+  PRINT_BIT_FIELD (Edx, L3CacheQosEnforcement);
+}
+
+/**
+  Display CPUID_PLATFORM_QOS_MONITORING capability sub-leaf.
+
+**/
+VOID
+CpuidPlatformQosMonitoringCapabilitySubLeaf (
+  VOID
+  )
+{
+  UINT32                                                 Ebx;
+  UINT32                                                 Ecx;
+  CPUID_PLATFORM_QOS_MONITORING_CAPABILITY_SUB_LEAF_EDX  Edx;
+
+  if (CPUID_PLATFORM_QOS_MONITORING > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuidEx (
+    CPUID_PLATFORM_QOS_MONITORING, 
CPUID_PLATFORM_QOS_MONITORING_CAPABILITY_SUB_LEAF,
+    NULL, &Ebx, &Ecx, &Edx.Uint32
+    );
+  Print (L"CPUID_PLATFORM_QOS_MONITORING (Leaf %08x, Sub-Leaf %08x)\n", 
CPUID_PLATFORM_QOS_MONITORING, 
CPUID_PLATFORM_QOS_MONITORING_CAPABILITY_SUB_LEAF);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", 0, Ebx, Ecx, 
Edx.Uint32);
+  PRINT_VALUE     (Ebx, OccupancyConversionFactor);
+  PRINT_VALUE     (Ecx, Maximum_RMID_Range);
+  PRINT_BIT_FIELD (Edx, L3CacheOccupancyMonitoring);
+}
+
+/**
+  Display CPUID_PLATFORM_QOS_ENFORCEMENT sub-leaf.
+
+**/
+VOID
+CpuidPlatformQosEnforcementResidSubLeaf (
+  VOID
+  )
+{
+  CPUID_PLATFORM_QOS_ENFORCEMENT_RESID_SUB_LEAF_EAX Eax;
+  UINT32                                            Ebx;
+  CPUID_PLATFORM_QOS_ENFORCEMENT_RESID_SUB_LEAF_ECX Ecx;
+  CPUID_PLATFORM_QOS_ENFORCEMENT_RESID_SUB_LEAF_EDX Edx;
+
+  AsmCpuidEx (
+    CPUID_PLATFORM_QOS_ENFORCEMENT, 
CPUID_PLATFORM_QOS_ENFORCEMENT_RESID_SUB_LEAF,
+    &Eax.Uint32, &Ebx, &Ecx.Uint32, &Edx.Uint32
+    );
+  Print (L"CPUID_PLATFORM_QOS_ENFORCEMENT (Leaf %08x, Sub-Leaf %08x)\n", 
CPUID_PLATFORM_QOS_ENFORCEMENT, CPUID_PLATFORM_QOS_ENFORCEMENT_RESID_SUB_LEAF);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, Ebx, 
Ecx.Uint32, Edx.Uint32);
+  PRINT_BIT_FIELD (Eax, CapacityLength);
+  PRINT_VALUE     (Ebx, AllocationUnitBitMap);
+  PRINT_BIT_FIELD (Ecx, CosUpdatesInfrequent);
+  PRINT_BIT_FIELD (Ecx, CodeDataPrioritization);
+  PRINT_BIT_FIELD (Edx, HighestCosNumber);
+}
+
+/**
+  Display CPUID_PLATFORM_QOS_ENFORCEMENT main leaf and sub-leaf.
+
+**/
+VOID
+CpuidPlatformQosEnforcementMainLeaf (
+  VOID
+  )
+{
+  CPUID_PLATFORM_QOS_ENFORCEMENT_MAIN_LEAF_EBX  Ebx;
+
+  if (CPUID_PLATFORM_QOS_ENFORCEMENT > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuidEx (
+    CPUID_PLATFORM_QOS_ENFORCEMENT, CPUID_PLATFORM_QOS_ENFORCEMENT_MAIN_LEAF,
+    NULL, &Ebx.Uint32, NULL, NULL
+    );
+  Print (L"CPUID_PLATFORM_QOS_ENFORCEMENT (Leaf %08x, Sub-Leaf %08x)\n", 
CPUID_PLATFORM_QOS_ENFORCEMENT, CPUID_PLATFORM_QOS_ENFORCEMENT_MAIN_LEAF);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", 0, Ebx.Uint32, 0, 0);
+  PRINT_BIT_FIELD (Ebx, L3CacheQosEnforcement);
+
+  CpuidPlatformQosEnforcementResidSubLeaf ();
+}
+
+/**
+  Display CPUID_INTEL_PROCESSOR_TRACE sub-leafs.
+
+  @param[in] MaximumSubLeaf  Maximum sub-leaf index for 
CPUID_INTEL_PROCESSOR_TRACE.
+
+**/
+VOID
+CpuidIntelProcessorTraceSubLeaf (
+  UINT32  MaximumSubLeaf
+  )
+{
+  UINT32                                    SubLeaf;
+  CPUID_INTEL_PROCESSOR_TRACE_SUB_LEAF_EAX  Eax;
+  CPUID_INTEL_PROCESSOR_TRACE_SUB_LEAF_EBX  Ebx;
+
+  for (SubLeaf = CPUID_INTEL_PROCESSOR_TRACE_SUB_LEAF; SubLeaf <= 
MaximumSubLeaf; SubLeaf++) {
+    AsmCpuidEx (
+      CPUID_INTEL_PROCESSOR_TRACE, SubLeaf,
+      &Eax.Uint32, &Ebx.Uint32, NULL, NULL
+      );
+    Print (L"CPUID_INTEL_PROCESSOR_TRACE (Leaf %08x, Sub-Leaf %08x)\n", 
CPUID_INTEL_PROCESSOR_TRACE, SubLeaf);
+    Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, 0, 0);
+    PRINT_BIT_FIELD (Eax, ConfigurableAddressRanges);
+    PRINT_BIT_FIELD (Eax, MtcPeriodEncodings);
+    PRINT_BIT_FIELD (Ebx, CycleThresholdEncodings);
+    PRINT_BIT_FIELD (Ebx, PsbFrequencyEncodings);
+  }
+}
+
+/**
+  Display CPUID_INTEL_PROCESSOR_TRACE main leaf and sub-leafs.
+
+**/
+VOID
+CpuidIntelProcessorTraceMainLeaf (
+  VOID
+  )
+{
+  UINT32                                     Eax;
+  CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_EBX  Ebx;
+  CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF_ECX  Ecx;
+
+  if (CPUID_INTEL_PROCESSOR_TRACE > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuidEx (
+    CPUID_INTEL_PROCESSOR_TRACE, CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF,
+    &Eax, &Ebx.Uint32, &Ecx.Uint32, NULL
+    );
+  Print (L"CPUID_INTEL_PROCESSOR_TRACE (Leaf %08x, Sub-Leaf %08x)\n", 
CPUID_INTEL_PROCESSOR_TRACE, CPUID_INTEL_PROCESSOR_TRACE_MAIN_LEAF);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, Ebx.Uint32, 
Ecx.Uint32, 0);
+  PRINT_VALUE     (Eax, MaximumSubLeaf);
+  PRINT_BIT_FIELD (Ebx, Cr3Filter);
+  PRINT_BIT_FIELD (Ebx, ConfigurablePsb);
+  PRINT_BIT_FIELD (Ebx, IpTraceStopFiltering);
+  PRINT_BIT_FIELD (Ebx, Mtc);
+  PRINT_BIT_FIELD (Ecx, RTIT);
+  PRINT_BIT_FIELD (Ecx, ToPA);
+  PRINT_BIT_FIELD (Ecx, SingleRangeOutput);
+  PRINT_BIT_FIELD (Ecx, TraceTransportSubsystem);
+  PRINT_BIT_FIELD (Ecx, LIP);
+
+  CpuidIntelProcessorTraceSubLeaf (Eax);
+}
+
+/**
+  Display CPUID_TIME_STAMP_COUNTER leaf.
+
+**/
+VOID
+CpuidTimeStampCounter (
+  VOID
+  )
+{
+  UINT32  Eax;
+  UINT32  Ebx;
+
+  if (CPUID_TIME_STAMP_COUNTER > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_TIME_STAMP_COUNTER, &Eax, &Ebx, NULL, NULL);
+  Print (L"CPUID_TIME_STAMP_COUNTER (Leaf %08x)\n", CPUID_TIME_STAMP_COUNTER);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, Ebx, 0, 0);
+}
+
+/**
+  Display CPUID_PROCESSOR_FREQUENCY leaf.
+
+**/
+VOID
+CpuidProcessorFrequency (
+  VOID
+  )
+{
+  CPUID_PROCESSOR_FREQUENCY_EAX  Eax;
+  CPUID_PROCESSOR_FREQUENCY_EBX  Ebx;
+  CPUID_PROCESSOR_FREQUENCY_ECX  Ecx;
+
+  if (CPUID_PROCESSOR_FREQUENCY > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_PROCESSOR_FREQUENCY, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, 
NULL);
+  Print (L"CPUID_PROCESSOR_FREQUENCY (Leaf %08x)\n", 
CPUID_PROCESSOR_FREQUENCY);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, Ecx.Uint32, 0);
+  PRINT_BIT_FIELD (Eax, ProcessorBaseFrequency);
+  PRINT_BIT_FIELD (Ebx, MaximumFrequency);
+  PRINT_BIT_FIELD (Ecx, BusFrequency);
+}
+
+/**
+  Display CPUID_SOC_VENDOR sub-leafs that contain the SoC Vendor Brand String.
+  Also display these sub-leafs as a single SoC Vendor Brand String.
+
+**/
+VOID
+CpuidSocVendorBrandString (
+  VOID
+  )
+{
+  CPUID_SOC_VENDOR_BRAND_STRING_DATA  Eax;
+  CPUID_SOC_VENDOR_BRAND_STRING_DATA  Ebx;
+  CPUID_SOC_VENDOR_BRAND_STRING_DATA  Ecx;
+  CPUID_SOC_VENDOR_BRAND_STRING_DATA  Edx;
+  //
+  // Array to store brand string from 3 brand string leafs with
+  // 4 32-bit brand string values per leaf and an extra value to
+  // null terminate the string.
+  //
+  UINT32                              BrandString[3 * 4 + 1];
+
+  AsmCpuidEx (
+    CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING1,
+    &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32
+    );
+  Print (L"CPUID_SOC_VENDOR (Leaf %08x, Sub-Leaf %08x)\n", CPUID_SOC_VENDOR, 
CPUID_SOC_VENDOR_BRAND_STRING1);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+  BrandString[0] = Eax.Uint32;
+  BrandString[1] = Ebx.Uint32;
+  BrandString[2] = Ecx.Uint32;
+  BrandString[3] = Edx.Uint32;
+
+  AsmCpuidEx (
+    CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING2,
+    &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32
+    );
+  Print (L"CPUID_SOC_VENDOR (Leaf %08x, Sub-Leaf %08x)\n", CPUID_SOC_VENDOR, 
CPUID_SOC_VENDOR_BRAND_STRING2);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+  BrandString[4] = Eax.Uint32;
+  BrandString[5] = Ebx.Uint32;
+  BrandString[6] = Ecx.Uint32;
+  BrandString[7] = Edx.Uint32;
+
+  AsmCpuidEx (
+    CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_BRAND_STRING3,
+    &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, &Edx.Uint32
+    );
+  Print (L"CPUID_SOC_VENDOR (Leaf %08x, Sub-Leaf %08x)\n", CPUID_SOC_VENDOR, 
CPUID_SOC_VENDOR_BRAND_STRING3);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+  BrandString[8]  = Eax.Uint32;
+  BrandString[9]  = Ebx.Uint32;
+  BrandString[10] = Ecx.Uint32;
+  BrandString[11] = Edx.Uint32;
+
+  BrandString[12] = 0;
+
+  Print (L"Vendor Brand String = %a\n", (CHAR8 *)BrandString);
+}
+
+/**
+  Display CPUID_SOC_VENDOR main leaf and sub-leafs.
+
+**/
+VOID
+CpuidSocVendor (
+  VOID
+  )
+{
+  UINT32                          Eax;
+  CPUID_SOC_VENDOR_MAIN_LEAF_EBX  Ebx;
+  UINT32                          Ecx;
+  UINT32                          Edx;
+
+  if (CPUID_SOC_VENDOR > gMaximumBasicFunction) {
+    return;
+  }
+
+  AsmCpuidEx (
+    CPUID_SOC_VENDOR, CPUID_SOC_VENDOR_MAIN_LEAF,
+    &Eax, &Ebx.Uint32, &Ecx, &Edx
+    );
+  Print (L"CPUID_SOC_VENDOR (Leaf %08x, Sub-Leaf %08x)\n", CPUID_SOC_VENDOR, 
CPUID_SOC_VENDOR_MAIN_LEAF);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, Ebx.Uint32, Ecx, 
Edx);
+  if (Eax < 3) {
+    Print (L"  Not Supported\n");
+    return;
+  }
+  PRINT_VALUE     (Eax, MaxSOCID_Index);
+  PRINT_BIT_FIELD (Ebx, SocVendorId);
+  PRINT_BIT_FIELD (Ebx, IsVendorScheme);
+  PRINT_VALUE     (Ecx, ProjectID);
+  PRINT_VALUE     (Edx, SteppingID);
+  CpuidSocVendorBrandString ();
+}
+
+/**
+  Display CPUID_EXTENDED_FUNCTION leaf.
+
+**/
+VOID
+CpuidExtendedFunction (
+  VOID
+  )
+{
+  UINT32  Eax;
+
+  AsmCpuid (CPUID_EXTENDED_FUNCTION, &Eax, NULL, NULL, NULL);
+  Print (L"CPUID_EXTENDED_FUNCTION (Leaf %08x)\n", CPUID_EXTENDED_FUNCTION);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, 0, 0, 0);
+  PRINT_VALUE     (Eax, MaximumExtendedFunction);
+
+  gMaximumExtendedFunction = Eax;
+}
+
+/**
+  Display CPUID_EXTENDED_CPU_SIG leaf.
+
+**/
+VOID
+CpuidExtendedCpuSig (
+  VOID
+  )
+{
+  UINT32                      Eax;
+  CPUID_EXTENDED_CPU_SIG_ECX  Ecx;
+  CPUID_EXTENDED_CPU_SIG_EDX  Edx;
+
+  if (CPUID_EXTENDED_CPU_SIG > gMaximumExtendedFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_EXTENDED_CPU_SIG, &Eax, NULL, &Ecx.Uint32, &Edx.Uint32);
+  Print (L"CPUID_EXTENDED_CPU_SIG (Leaf %08x)\n", CPUID_EXTENDED_CPU_SIG);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax, 0, Ecx.Uint32, 
Edx.Uint32);
+  PRINT_BIT_FIELD (Ecx, LAHF_SAHF);
+  PRINT_BIT_FIELD (Ecx, LZCNT);
+  PRINT_BIT_FIELD (Ecx, PREFETCHW);
+  PRINT_BIT_FIELD (Edx, SYSCALL_SYSRET);
+  PRINT_BIT_FIELD (Edx, NX);
+  PRINT_BIT_FIELD (Edx, Page1GB);
+  PRINT_BIT_FIELD (Edx, RDTSCP);
+  PRINT_BIT_FIELD (Edx, LM);
+}
+
+/**
+  Display CPUID_BRAND_STRING1, CPUID_BRAND_STRING2 and  CPUID_BRAND_STRING3
+  leafs.  Also display these three leafs as a single brand string.
+
+**/
+VOID
+CpuidProcessorBrandString (
+  VOID
+  )
+{
+  CPUID_BRAND_STRING_DATA  Eax;
+  CPUID_BRAND_STRING_DATA  Ebx;
+  CPUID_BRAND_STRING_DATA  Ecx;
+  CPUID_BRAND_STRING_DATA  Edx;
+  //
+  // Array to store brand string from 3 brand string leafs with
+  // 4 32-bit brand string values per leaf and an extra value to
+  // null terminate the string.
+  //
+  UINT32                   BrandString[3 * 4 + 1];
+
+  if (CPUID_BRAND_STRING1 <= gMaximumExtendedFunction) {
+    AsmCpuid (CPUID_BRAND_STRING1, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, 
&Edx.Uint32);
+    Print (L"CPUID_BRAND_STRING1 (Leaf %08x)\n", CPUID_BRAND_STRING1);
+    Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+    BrandString[0] = Eax.Uint32;
+    BrandString[1] = Ebx.Uint32;
+    BrandString[2] = Ecx.Uint32;
+    BrandString[3] = Edx.Uint32;
+  }
+
+  if (CPUID_BRAND_STRING2 <= gMaximumExtendedFunction) {
+    AsmCpuid (CPUID_BRAND_STRING2, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, 
&Edx.Uint32);
+    Print (L"CPUID_BRAND_STRING2 (Leaf %08x)\n", CPUID_BRAND_STRING2);
+    Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+    BrandString[4] = Eax.Uint32;
+    BrandString[5] = Ebx.Uint32;
+    BrandString[6] = Ecx.Uint32;
+    BrandString[7] = Edx.Uint32;
+  }
+
+  if (CPUID_BRAND_STRING3 <= gMaximumExtendedFunction) {
+    AsmCpuid (CPUID_BRAND_STRING3, &Eax.Uint32, &Ebx.Uint32, &Ecx.Uint32, 
&Edx.Uint32);
+    Print (L"CPUID_BRAND_STRING3 (Leaf %08x)\n", CPUID_BRAND_STRING3);
+    Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 
Ebx.Uint32, Ecx.Uint32, Edx.Uint32);
+    BrandString[8]  = Eax.Uint32;
+    BrandString[9]  = Ebx.Uint32;
+    BrandString[10] = Ecx.Uint32;
+    BrandString[11] = Edx.Uint32;
+  }
+
+  BrandString[12] = 0;
+
+  Print (L"Brand String = %a\n", (CHAR8 *)BrandString);
+}
+
+/**
+  Display CPUID_EXTENDED_CACHE_INFO leaf.
+
+**/
+VOID
+CpuidExtendedCacheInfo (
+  VOID
+  )
+{
+  CPUID_EXTENDED_CACHE_INFO_ECX  Ecx;
+
+  if (CPUID_EXTENDED_CACHE_INFO > gMaximumExtendedFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_EXTENDED_CACHE_INFO, NULL, NULL, &Ecx.Uint32, NULL);
+  Print (L"CPUID_EXTENDED_CACHE_INFO (Leaf %08x)\n", 
CPUID_EXTENDED_CACHE_INFO);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", 0, 0, Ecx.Uint32, 0);
+  PRINT_BIT_FIELD (Ecx, CacheLineSize);
+  PRINT_BIT_FIELD (Ecx, L2Associativity);
+  PRINT_BIT_FIELD (Ecx, CacheSize);
+}
+
+/**
+  Display CPUID_EXTENDED_TIME_STAMP_COUNTER leaf.
+
+**/
+VOID
+CpuidExtendedTimeStampCounter (
+  VOID
+  )
+{
+  CPUID_EXTENDED_TIME_STAMP_COUNTER_EDX  Edx;
+
+  if (CPUID_EXTENDED_TIME_STAMP_COUNTER > gMaximumExtendedFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_EXTENDED_TIME_STAMP_COUNTER, NULL, NULL, NULL, &Edx.Uint32);
+  Print (L"CPUID_EXTENDED_TIME_STAMP_COUNTER (Leaf %08x)\n", 
CPUID_EXTENDED_TIME_STAMP_COUNTER);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", 0, 0, 0, Edx.Uint32);
+  PRINT_BIT_FIELD (Edx, InvariantTsc);
+}
+
+/**
+  Display CPUID_VIR_PHY_ADDRESS_SIZE leaf.
+
+**/
+VOID
+CpuidVirPhyAddressSize (
+  VOID
+  )
+{
+  CPUID_VIR_PHY_ADDRESS_SIZE_EAX  Eax;
+
+  if (CPUID_VIR_PHY_ADDRESS_SIZE > gMaximumExtendedFunction) {
+    return;
+  }
+
+  AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &Eax.Uint32, NULL, NULL, NULL);
+  Print (L"CPUID_VIR_PHY_ADDRESS_SIZE (Leaf %08x)\n", 
CPUID_VIR_PHY_ADDRESS_SIZE);
+  Print (L"  EAX:%08x  EBX:%08x  ECX:%08x  EDX:%08x\n", Eax.Uint32, 0, 0, 0);
+  PRINT_BIT_FIELD (Eax, PhysicalAddressBits);
+  PRINT_BIT_FIELD (Eax, LinearAddressBits);
+}
+
+/**
+  The user Entry Point for Application. The user code starts with this function
+  as the real entry point for the application.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  Print (L"UEFI CPUID Version 0.5\n");
+
+  CpuidSignature ();
+  CpuidVersionInfo ();
+  CpuidCacheInfo ();
+  CpuidSerialNumber ();
+  CpuidCacheParams();
+  CpuidMonitorMwait ();
+  CpuidThermalPowerManagement ();
+  CpuidStructuredExtendedFeatureFlags ();
+  CpuidDirectCacheAccessInfo();
+  CpuidArchitecturalPerformanceMonitoring ();
+  CpuidExtendedTopology ();
+  CpuidExtendedStateMainLeaf ();
+  CpuidPlatformQosMonitoringEnumerationSubLeaf ();
+  CpuidPlatformQosMonitoringCapabilitySubLeaf ();
+  CpuidPlatformQosEnforcementMainLeaf ();
+  CpuidIntelProcessorTraceMainLeaf ();
+  CpuidTimeStampCounter ();
+  CpuidProcessorFrequency ();
+  CpuidSocVendor ();
+  CpuidExtendedFunction ();
+  CpuidExtendedCpuSig ();
+  CpuidProcessorBrandString ();
+  CpuidExtendedCacheInfo ();
+  CpuidExtendedTimeStampCounter ();
+  CpuidVirPhyAddressSize ();
+
+  return EFI_SUCCESS;
+}
diff --git a/UefiCpuPkg/Application/Cpuid/Cpuid.inf 
b/UefiCpuPkg/Application/Cpuid/Cpuid.inf
new file mode 100644
index 0000000..0d71b11
--- /dev/null
+++ b/UefiCpuPkg/Application/Cpuid/Cpuid.inf
@@ -0,0 +1,48 @@
+## @file
+#  UEFI Application to display CPUID leaf information.
+#
+#  This UEFI application displays the registers values returned by CPUID for
+#  all the CPUID leafs and sub-leafs that a CPU supports.  It also displays
+#  the values of all the bit fields in the registers returned by each CPUID
+#  leaf and sub-leaf.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD 
License
+#  which accompanies this distribution. The full text of the license may be 
found at
+#  http://opensource.org/licenses/bsd-license.php
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Cpuid
+  MODULE_UNI_FILE                = Cpuid.uni
+  FILE_GUID                      = 4AE7E1E8-9DFE-4e3e-85B4-A5F6ABD470FB
+  MODULE_TYPE                    = UEFI_APPLICATION
+  VERSION_STRING                 = 0.5
+  ENTRY_POINT                    = UefiMain
+
+#
+# The following information is for reference only and not required by the 
build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  Cpuid.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  UefiApplicationEntryPoint
+  BaseLib
+  UefiLib
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  CpuidExtra.uni
diff --git a/UefiCpuPkg/Application/Cpuid/Cpuid.uni 
b/UefiCpuPkg/Application/Cpuid/Cpuid.uni
new file mode 100644
index 0000000..32dee43
--- /dev/null
+++ b/UefiCpuPkg/Application/Cpuid/Cpuid.uni
@@ -0,0 +1,22 @@
+// /** @file
+// UEFI Application to display CPUID leaf information.
+//
+// This UEFI application displays the registers values returned by CPUID for
+// all the CPUID leafs and sub-leafs that a CPU supports.  It also displays
+// the values of all the bit fields in the registers returned by each CPUID
+// leaf and sub-leaf.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD 
License
+// which accompanies this distribution. The full text of the license may be 
found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+//
+// **/
+
+#string STR_MODULE_ABSTRACT             #language en-US "UEFI Application to 
display CPUID leaf information"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This UEFI application 
displays the registers values returned by CPUID for all the CPUID leafs and 
sub-leafs that a CPU supports.  It also displays the values of all the bit 
fields in the registers returned by each CPUID leaf and sub-leaf."
diff --git a/UefiCpuPkg/Application/Cpuid/CpuidExtra.uni 
b/UefiCpuPkg/Application/Cpuid/CpuidExtra.uni
new file mode 100644
index 0000000..b4251e2
--- /dev/null
+++ b/UefiCpuPkg/Application/Cpuid/CpuidExtra.uni
@@ -0,0 +1,22 @@
+// /** @file
+// UEFI Application to display CPUID leaf information.
+//
+// This UEFI application displays the registers values returned by CPUID for
+// all the CPUID leafs and sub-leafs that a CPU supports.  It also displays
+// the values of all the bit fields in the registers returned by each CPUID
+// leaf and sub-leaf.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD 
License
+// which accompanies this distribution. The full text of the license may be 
found at
+// http://opensource.org/licenses/bsd-license.php
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"CPUID Application"
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 31e60bb..7319152 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -88,6 +88,10 @@
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
   
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
 
+[LibraryClasses.common.UEFI_APPLICATION]
+  
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+  
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+
 #
 # Drivers/Libraries within this package
 #
@@ -96,6 +100,7 @@
   UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
   UefiCpuPkg/CpuIoPei/CpuIoPei.inf
   UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf
+  UefiCpuPkg/Application/Cpuid/Cpuid.inf
 
 [Components.IA32, Components.X64]
   UefiCpuPkg/CpuDxe/CpuDxe.inf
-- 
2.6.3.windows.1

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to