v1.0.1
diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.c b/IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.c
new file mode 100644
index 0000000..145d3a6
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.c
@@ -0,0 +1,705 @@
+/** @file

+

+  Entry point of CPU DXE driver.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  Cpu.c

+

+**/

+

+#include "Cpu.h"

+

+//

+// CPU System Memory Map Definition

+//

+#define CPU_MSI_MEMORY_BASE                   0xFEE00000

+#define CPU_MSI_MEMORY_SIZE                   0x100000

+

+BOOLEAN                     mIsFlushingGCD;

+EFI_HANDLE                  mHandle = NULL;

+

+//

+// Vector Table for user's interrupt handlers

+//

+EFI_CPU_INTERRUPT_HANDLER   mExternalVectorTable[INTERRUPT_VECTOR_NUMBER];

+

+//

+// The Cpu Architectural Protocol that this Driver produces

+//

+EFI_CPU_ARCH_PROTOCOL       mCpuArchProtocol = {

+  FlushCpuDataCache,

+  EnableInterrupt,

+  DisableInterrupt,

+  GetInterruptStateInstance,

+  Init,

+  RegisterInterruptHandler,

+  GetTimerValue,

+  SetMemoryAttributes,

+  1,

+  4,

+};

+

+/**

+  This function flushes CPU data cache.

+

+  This function implements FlushDataCache() service of CPU Architecture Protocol.

+  It flushes a range of the processor's data cache.

+

+  @param  This              The EFI_CPU_ARCH_PROTOCOL instance.

+  @param  Start             Physical address to start flushing from.

+  @param  Length            Number of bytes to flush. Round up to chipset granularity.

+  @param  FlushType         Specifies the type of flush operation to perform.

+

+  @retval EFI_SUCCESS       Cache is flushed.

+  @retval EFI_UNSUPPORTED   Flush type is not supported.

+  @retval EFI_DEVICE_ERROR  Requested range could not be flushed..

+

+**/

+EFI_STATUS

+EFIAPI

+FlushCpuDataCache (

+  IN EFI_CPU_ARCH_PROTOCOL     *This,

+  IN EFI_PHYSICAL_ADDRESS      Start,

+  IN UINT64                    Length,

+  IN EFI_CPU_FLUSH_TYPE        FlushType

+  )

+{

+  if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {

+    AsmWbinvd ();

+    return EFI_SUCCESS;

+  } else if (FlushType == EfiCpuFlushTypeInvalidate) {

+    AsmInvd ();

+    return EFI_SUCCESS;

+  } else {

+    return EFI_UNSUPPORTED;

+  }

+}

+

+/**

+  This function enables interrupt processing by the processor.

+

+  This function implements EnableInterrupt() service of CPU Architecture Protocol.

+  This function enables interrupt processing by the processor. This function is

+  used to implement the Boot Services RaiseTPL() and RestoreTPL().

+

+  @param  This              The EFI_CPU_ARCH_PROTOCOL instance.

+

+  @retval EFI_SUCCESS       Interrupts are enabled on the processor.

+  @retval EFI_DEVICE_ERROR  Interrupts could not be enabled on the processor.

+

+**/

+EFI_STATUS

+EFIAPI

+EnableInterrupt (

+  IN EFI_CPU_ARCH_PROTOCOL          *This

+  )

+{

+  EnableInterrupts ();

+  return EFI_SUCCESS;

+}

+

+/**

+  This function disables interrupt processing by the processor.

+

+  This function implements DisableInterrupt() service of CPU Architecture Protocol.

+  This function disables interrupt processing by the processor. This function is

+  used to implement the Boot Services RaiseTPL() and RestoreTPL().

+

+  @param  This              The EFI_CPU_ARCH_PROTOCOL instance.

+

+  @retval EFI_SUCCESS       Interrupts are disabled on the processor.

+  @retval EFI_DEVICE_ERROR  Interrupts could not be disabled on the processor.

+

+**/

+EFI_STATUS

+EFIAPI

+DisableInterrupt (

+  IN EFI_CPU_ARCH_PROTOCOL     *This

+  )

+{

+  DisableInterrupts ();

+  return EFI_SUCCESS;

+}

+

+/**

+  This function retrieves the processor's current interrupt state.

+

+  This function implements GetInterruptState() service of CPU Architecture Protocol.

+  This function retrieves the processor's current interrupt state.

+

+  @param  This                   The EFI_CPU_ARCH_PROTOCOL instance.

+  @param  State                  A pointer to the processor's current interrupt state.

+                                 Set to TRUE if interrupts are enabled and FALSE if interrupts are disabled.

+

+  @retval EFI_SUCCESS            The processor's current interrupt state was returned in State.

+  @retval EFI_INVALID_PARAMETER  State is NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+GetInterruptStateInstance (

+  IN  EFI_CPU_ARCH_PROTOCOL     *This,

+  OUT BOOLEAN                   *State

+  )

+{

+  if (State == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  *State = GetInterruptState ();

+  return EFI_SUCCESS;

+}

+

+/**

+  This function generates an INIT on the processor.

+

+  This function implements Init() service of CPU Architecture Protocol.

+  This function generates an INIT on the processor.

+

+  @param  This                   The EFI_CPU_ARCH_PROTOCOL instance.

+  @param  InitType               The type of processor INIT to perform.

+

+  @retval EFI_SUCCESS            The processor INIT was performed. This return code should never be seen.

+  @retval EFI_UNSUPPORTED        The processor INIT operation specified by InitType is not supported by this processor.

+  @retval EFI_DEVICE_ERROR       The processor INIT failed.

+

+**/

+EFI_STATUS

+EFIAPI

+Init (

+  IN EFI_CPU_ARCH_PROTOCOL      *This,

+  IN EFI_CPU_INIT_TYPE          InitType

+  )

+{

+  return EFI_UNSUPPORTED;

+}

+

+/**

+  This function Registers a function to be called from the processor interrupt handler.

+

+  This function implements RegisterInterruptHandler() service of CPU Architecture Protocol.

+  This function Registers a function to be called from the processor interrupt handler.

+

+  @param  This                   The EFI_CPU_ARCH_PROTOCOL instance.

+  @param  InterruptType          Defines which interrupt or exception to hook.

+  @param  InterruptHandler       A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER

+                                 that is called when a processor interrupt occurs.

+                                 If this parameter is NULL, then the handler will be uninstalled.

+

+  @retval EFI_SUCCESS            The handler for the processor interrupt was successfully installed or uninstalled.

+  @retval EFI_ALREADY_STARTED    InterruptHandler is not NULL, and a handler for InterruptType was previously installed.

+  @retval EFI_INVALID_PARAMETER  InterruptHandler is NULL, and a handler for InterruptType was not previously installed.

+  @retval EFI_UNSUPPORTED        The interrupt specified by InterruptType is not supported.

+

+**/

+EFI_STATUS

+EFIAPI

+RegisterInterruptHandler (

+  IN EFI_CPU_ARCH_PROTOCOL         *This,

+  IN EFI_EXCEPTION_TYPE            InterruptType,

+  IN EFI_CPU_INTERRUPT_HANDLER     InterruptHandler

+  )

+{

+  if (InterruptType < 0 || InterruptType > 0xff) {

+    return EFI_UNSUPPORTED;

+  }

+

+  if (InterruptHandler == NULL && mExternalVectorTable[InterruptType] == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  if (InterruptHandler != NULL && mExternalVectorTable[InterruptType] != NULL) {

+    return EFI_ALREADY_STARTED;

+  }

+

+  if (InterruptHandler != NULL) {

+    SetInterruptDescriptorTableHandlerAddress ((UINTN)InterruptType);

+  } else {

+    //

+    // Restore the original IDT handler address if InterruptHandler is NULL.

+    //

+    RestoreInterruptDescriptorTableHandlerAddress ((UINTN)InterruptType);

+  }

+

+  mExternalVectorTable[InterruptType] = InterruptHandler;

+  return EFI_SUCCESS;

+}

+

+/**

+  This function returns a timer value from one of the processor's internal timers.

+

+  This function implements GetTimerValue() service of CPU Architecture Protocol.

+  This function returns a timer value from one of the processor's internal timers.

+

+  @param  This                   The EFI_CPU_ARCH_PROTOCOL instance.

+  @param  TimerIndex             Specifies which processor timer is to be returned in TimerValue.

+                                 This parameter must be between 0 and EFI_CPU_ARCH_PROTOCOL.NumberOfTimers-1.

+  @param  TimerValue             Pointer to the returned timer value.

+  @param  TimerPeriod            A pointer to the amount of time that passes in femtoseconds for each

+                                 increment of TimerValue. If TimerValue does not increment at a predictable

+                                 rate, then 0 is returned.

+

+  @retval EFI_SUCCESS            The processor timer value specified by TimerIndex was returned in TimerValue.

+  @retval EFI_INVALID_PARAMETER  TimerValue is NULL.

+  @retval EFI_INVALID_PARAMETER  TimerIndex is not valid.

+  @retval EFI_UNSUPPORTEDT       The processor does not have any readable timers.

+  @retval EFI_DEVICE_ERROR       An error occurred attempting to read one of the processor's timers.

+

+**/

+EFI_STATUS

+EFIAPI

+GetTimerValue (

+  IN  EFI_CPU_ARCH_PROTOCOL     *This,

+  IN  UINT32                    TimerIndex,

+  OUT UINT64                    *TimerValue,

+  OUT UINT64                    *TimerPeriod OPTIONAL

+  )

+{

+  EFI_STATUS      Status;

+  UINT64          Actual;

+  UINT64          Standard;

+  UINT32          Ratio;

+  

+  if (TimerValue == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  if (TimerIndex != 0) {

+    return EFI_INVALID_PARAMETER;

+  }

+  

+  *TimerValue = AsmReadTsc ();

+  

+  if (TimerPeriod != NULL) {

+    Status = GetActualFrequency (&Actual);

+    ASSERT_EFI_ERROR (Status);

+    

+    Status = GetCpuBusRatio (&Ratio);

+    ASSERT_EFI_ERROR (Status);

+    

+    //

+    // Since actual frequency might not be accurate, convert it into standand

+    // frequency: 100, 133, 166, 200, ...

+    //

+    Actual2StandardFrequency (Actual, Ratio, &Standard);

+    

+    *TimerPeriod = DivU64x32 (1000000000, (UINT32) Standard);

+  }

+  

+  return EFI_SUCCESS;

+}

+

+/**

+  Implementation of SetMemoryAttributes() service of CPU Architecture Protocol.

+

+  This function modifies the attributes for the memory region specified by BaseAddress and

+  Length from their current attributes to the attributes specified by Attributes.

+

+  @param  This             The EFI_CPU_ARCH_PROTOCOL instance.

+  @param  BaseAddress      The physical address that is the start address of a memory region.

+  @param  Length           The size in bytes of the memory region.

+  @param  Attributes       The bit mask of attributes to set for the memory region.

+

+  @retval EFI_SUCCESS           The attributes were set for the memory region.

+  @retval EFI_ACCESS_DENIED     The attributes for the memory resource range specified by

+                                BaseAddress and Length cannot be modified.

+  @retval EFI_INVALID_PARAMETER Length is zero.

+                                Attributes specified an illegal combination of attributes that

+                                cannot be set together.

+  @retval EFI_OUT_OF_RESOURCES  There are not enough system resources to modify the attributes of

+                                the memory resource range.

+  @retval EFI_UNSUPPORTED       The processor does not support one or more bytes of the memory

+                                resource range specified by BaseAddress and Length.

+                                The bit mask of attributes is not support for the memory resource

+                                range specified by BaseAddress and Length.

+

+**/

+EFI_STATUS

+EFIAPI

+SetMemoryAttributes (

+  IN EFI_CPU_ARCH_PROTOCOL     *This,

+  IN EFI_PHYSICAL_ADDRESS      BaseAddress,

+  IN UINT64                    Length,

+  IN UINT64                    Attributes

+  )

+{

+  RETURN_STATUS             Status;

+  EFI_STATUS                MpStatus;

+  MTRR_MEMORY_CACHE_TYPE    CacheType;

+  EFI_MP_SERVICES_PROTOCOL  *MpService;

+

+  //

+  // If this function is called because GCD SetMemorySpaceAttributes () is called

+  // by RefreshGcdMemoryAttributes (), then we are just synchronzing GCD memory 

+  // map with MTRR values. So there is no need to modify MTRRs, just return immediately

+  // to avoid unnecessary computing.

+  //

+  if (mIsFlushingGCD) {

+    return EFI_SUCCESS;

+  }

+

+  switch (Attributes) {

+  case EFI_MEMORY_UC:

+    CacheType = CacheUncacheable;

+    break;

+

+  case EFI_MEMORY_WC:

+    CacheType = CacheWriteCombining;

+    break;

+

+  case EFI_MEMORY_WT:

+    CacheType = CacheWriteThrough;

+    break;

+

+  case EFI_MEMORY_WP:

+    CacheType = CacheWriteProtected;

+    break;

+

+  case EFI_MEMORY_WB:

+    CacheType = CacheWriteBack;

+    break;

+

+  case EFI_MEMORY_UCE:

+  case EFI_MEMORY_RP:

+  case EFI_MEMORY_XP:

+  case EFI_MEMORY_RUNTIME:

+    return EFI_UNSUPPORTED;

+

+  default:

+    return EFI_INVALID_PARAMETER;

+  }

+  //

+  // call MTRR libary function

+  //

+  Status = MtrrSetMemoryAttribute(

+             BaseAddress,

+             Length,

+             CacheType

+           );

+

+  if (!RETURN_ERROR (Status)) {

+    //

+    // Sync saved MTRR settings

+    //

+    MtrrGetAllMtrrs (mMtrrTable);

+    //

+    // Synchronize the update with all APs

+    //

+    MpStatus = gBS->LocateProtocol (

+                      &gEfiMpServiceProtocolGuid,

+                      NULL,

+                      (VOID **) &MpService

+                      );

+    if (!EFI_ERROR (MpStatus)) {

+      MpStatus = MpService->StartupAllAPs (

+                              MpService,

+                              LoadMtrrData,

+                              TRUE,

+                              NULL,

+                              0,

+                              NULL,

+                              NULL

+                              );

+      if (MpStatus == EFI_NOT_STARTED) {

+        //

+        // If no enabled APs exit in the system, return success

+        //

+        MpStatus = EFI_SUCCESS;

+      }

+      ASSERT_EFI_ERROR (MpStatus);

+    }

+  }

+  return (EFI_STATUS) Status;

+}

+

+/**

+  Entrypoint of CPU DXE module.

+  

+  This function is the entrypoint of CPU DXE module. It initializes system and installs

+  CPU Architecture Protocol. 

+

+  @param  ImageHandle   The firmware allocated handle for the EFI image.

+  @param  SystemTable   A pointer to the EFI System Table.

+  

+  @retval EFI_SUCCESS   The entrypoint always returns EFI_SUCCESS.

+

+**/

+EFI_STATUS

+EFIAPI

+InitializeCpu (

+  IN EFI_HANDLE                            ImageHandle,

+  IN EFI_SYSTEM_TABLE                      *SystemTable

+  )

+{

+  EFI_STATUS              Status;

+  EFI_PHYSICAL_ADDRESS    BaseAddress;

+

+  InitializeFloatingPointUnits ();

+

+  //

+  // Initialize GDT and IDT

+  //

+  InitializeDescriptorTables ();

+

+  //

+  // Install CPU Architectural Protocol

+  //

+  Status = gBS->InstallProtocolInterface (

+                  &mHandle,

+                  &gEfiCpuArchProtocolGuid,

+                  EFI_NATIVE_INTERFACE,

+                  &mCpuArchProtocol

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Refresh GCD memory space map according to MTRR value.

+  //

+  RefreshGcdMemoryAttributes ();

+

+  //

+  // Report memory space from 0xFEE00000 to 0xFEEFFFFF as memory mapped space for MSI (Message Signaled Interrupt).

+  // First, add memory space for MSI

+  //

+  BaseAddress = CPU_MSI_MEMORY_BASE;

+  Status = gDS->AddMemorySpace (

+                  EfiGcdMemoryTypeMemoryMappedIo, 

+                  BaseAddress,

+                  CPU_MSI_MEMORY_SIZE,

+                  EFI_MEMORY_UC

+                  );

+  ASSERT_EFI_ERROR (Status);

+  //

+  // Second, allocate this new added memory space.

+  //

+  Status = gDS->AllocateMemorySpace (

+                  EfiGcdAllocateAddress,

+                  EfiGcdMemoryTypeMemoryMappedIo,

+                  0,

+                  CPU_MSI_MEMORY_SIZE,

+                  &BaseAddress,

+                  ImageHandle,

+                  NULL

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // If the default local APIC base address has been changed, we need to add/allocate

+  // memory space for the 4K size of the local APIC memory range.

+  //

+  BaseAddress = (EFI_PHYSICAL_ADDRESS) GetLocalApicBaseAddress();

+  if (BaseAddress != CPU_MSI_MEMORY_BASE) {

+    Status = gDS->AddMemorySpace (

+                    EfiGcdMemoryTypeMemoryMappedIo, 

+                    BaseAddress,

+                    SIZE_4KB,

+                    EFI_MEMORY_UC

+                    );

+    ASSERT_EFI_ERROR (Status);

+

+    Status = gDS->AllocateMemorySpace (

+                    EfiGcdAllocateAddress,

+                    EfiGcdMemoryTypeMemoryMappedIo,

+                    0,

+                    SIZE_4KB,

+                    &BaseAddress,

+                    ImageHandle,

+                    NULL

+                    );

+    ASSERT_EFI_ERROR (Status);

+  }

+

+  // Program Local APIC for virtual wire mode. Enable Spurious

+  // Vector, program the LINT0 vector entry as ExtInt, and 

+  // program the LINT1 vector entry as NMI

+  //

+  ProgramVirtualWireMode ();

+

+  //

+  // Allocates ACPI NVS memory for MTRR data.

+  //

+  InitializeMtrrData ();

+  MtrrGetAllMtrrs (mMtrrTable);

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Returns the CPU core to processor bus frequency ratio.

+

+  This function returns the CPU core to processor bus frequency ratio.

+

+  @param   Ratio                   Pointer to the CPU core to processor bus frequency ratio.

+

+  @retval  EFI_SUCCESS             The ratio is returned successfully

+  @retval  EFI_UNSUPPORTED         The ratio cannot be measured

+  @retval  EFI_INVALID_PARAMETER   The input parameter is not valid

+

+**/

+EFI_STATUS

+GetCpuBusRatio (

+  OUT UINT32        *Ratio

+  )

+{

+  UINT32              RegEax;

+  UINT32              BasicFamilyId;

+  UINT32              FamilyId;

+  UINT32              ModelId;

+  UINT32              ExtendedModelId;

+

+  if (Ratio == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  AsmCpuid (EFI_CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);

+

+  //

+  // The Extended Family ID needs to be examined only when the Family ID is 0FH.

+  //

+  BasicFamilyId = BitFieldRead32 (RegEax, 8, 11);

+  FamilyId      = BasicFamilyId;

+  if (BasicFamilyId == 0x0F) {

+    FamilyId += BitFieldRead32 (RegEax, 20, 27);

+  }

+

+  //

+  // The Extended Model ID needs to be examined only when the Family ID is 06H or 0FH.

+  //

+  ModelId = BitFieldRead32 (RegEax, 4, 7);

+  if (BasicFamilyId == 0x06 || BasicFamilyId == 0x0f) {

+    ExtendedModelId = BitFieldRead32 (RegEax, 16, 19);

+    ModelId        += ExtendedModelId << 4;

+  }

+

+  switch (FamilyId) {

+  case PENTIUM_FAMILY_ID:

+    switch (ModelId) {

+    case QUARK_MODEL_ID:

+      //

+      // Collect core to bus ratio

+      //

+      *Ratio = (UINTN) 0x01;

+      break;

+

+    default:

+      return EFI_UNSUPPORTED;

+    }

+    break;

+

+  default:

+    return EFI_UNSUPPORTED;

+  }

+  return EFI_SUCCESS;

+}

+

+/**

+  Returns the actual CPU core frequency in MHz.

+

+  This function returns the actual CPU core frequency in MHz.

+

+  @param   Frequency              Pointer to the CPU core frequency.

+  

+  @retval  EFI_SUCCESS            The frequency is returned successfully.

+  @retval  EFI_INVALID_PARAMETER  Frequency is NULL.            

+

+**/

+EFI_STATUS

+GetActualFrequency (

+  OUT UINT64                        *Frequency

+  )

+{

+  UINT64  BeginValue;

+  UINT64  EndValue;

+

+  if (Frequency == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Read timestamp counter before and after delay of 100 microseconds

+  //

+  BeginValue = AsmReadTsc ();

+  MicroSecondDelay (100);

+  EndValue   = AsmReadTsc ();

+

+  //

+  // Calculate the actual frequency

+  //

+  *Frequency  = DivU64x32Remainder (EndValue - BeginValue, 100, NULL);

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Converts the actual frequency in MHz to the standard frequency in MHz.

+

+  This function converts the actual frequency in MHz to the standard frequency in MHz.

+

+  @param   Actual              Actual CPU core frequency.

+  @param   Ratio               CPU core to processor bus frequency ratio.

+  @param   Standard            Standard CPU core frequency.

+

+**/

+VOID

+Actual2StandardFrequency (

+  IN  UINT64     Actual,

+  IN  UINT32     Ratio,

+  OUT UINT64     *Standard

+  )

+{

+  UINT64  Inflated;

+  UINT64  Temp;

+

+  //

+  // Increase the Actual frequency a little, compute its

+  // corresponding FSB frequency, and then discard the small fractions of it, to

+  // get a clean, standard FSB frequency value.

+  //

+  // Increase Actual by 3%, since the error of actual frequency is within 1%.

+  //

+  Inflated = Actual + RShiftU64 (Actual, 5);

+

+  //

+  // The standard Fsb are: 100(300/3), 133(400/3), 166(500/3), 200(600/3), ...

+  // so if we are able to calculate the digit(3, 4, 5, 6, etc) at the hundred's

+  // position, the standard frequency can be calculated.

+  //

+  //

+  // So multiple the Inflated frequency by 3, divide it with Ratio, and divide

+  // it by 100, in order to get an integer (3, 4, 5, 6, ... respectively).

+  //

+  Temp = DivU64x32 (DivU64x32 (MultU64x32 (Inflated, 3), Ratio), 100);

+

+  //

+  // After getting the digit, convert it back to the Cpu frequency

+  //

+  *Standard = DivU64x32 (MultU64x32 (MultU64x32 (Temp, 100), Ratio), 3);

+}

+

diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.h b/IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.h
new file mode 100644
index 0000000..35b4257
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/Cpu.h
@@ -0,0 +1,401 @@
+/** @file

+

+  Include file for CPU DXE Module

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  Cpu.h

+

+**/

+

+#ifndef _CPU_DXE_H_

+#define _CPU_DXE_H_

+

+#include <PiDxe.h>

+

+#include "Exception.h"

+#include "ArchSpecificDef.h"

+

+#include <Protocol/MpService.h>

+#include <Guid/StatusCodeDataTypeId.h>

+#include <Protocol/Cpu.h>

+

+#include <Library/BaseLib.h>

+#include <Library/DebugLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/ReportStatusCodeLib.h>

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/PcdLib.h>

+#include <Library/IoLib.h>

+#include <Library/DxeServicesTableLib.h>

+#include <Library/TimerLib.h>

+#include <Library/MtrrLib.h>

+#include <Library/UefiLib.h>

+#include <Library/SocketLga775Lib.h>

+#include <Library/LocalApicLib.h>

+#include <Library/UefiCpuLib.h>

+

+#include "MemoryAttribute.h"

+#include "MtrrSync.h"

+#include "Exception.h"

+

+#define INTERRUPT_VECTOR_NUMBER    256

+#define INTERRUPT_GATE_ATTRIBUTE   0x8e00

+

+#define APIC_REGISTER_LOCAL_ID_OFFSET         0x20

+#define APIC_REGISTER_APIC_VERSION_OFFSET     0x30

+#define APIC_REGISTER_SPURIOUS_VECTOR_OFFSET  0xF0

+#define APIC_REGISTER_ICR_LOW_OFFSET          0x300

+#define APIC_REGISTER_ICR_HIGH_OFFSET         0x310

+#define APIC_REGISTER_LINT0_VECTOR_OFFSET     0x350

+#define APIC_REGISTER_LINT1_VECTOR_OFFSET     0x360

+

+extern EFI_CPU_ARCH_PROTOCOL       mCpuArchProtocol;

+extern UINT64                      mValidMtrrAddressMask;

+extern UINT64                      mValidMtrrBitsMask;

+

+/**

+  This function flushes CPU data cache.

+

+  This function implements FlushDataCache() service of CPU Architecture Protocol.

+  It flushes a range of the processor's data cache.

+

+  @param  This              The EFI_CPU_ARCH_PROTOCOL instance.

+  @param  Start             Physical address to start flushing from.

+  @param  Length            Number of bytes to flush. Round up to chipset granularity.

+  @param  FlushType         Specifies the type of flush operation to perform.

+

+  @retval EFI_SUCCESS       Cache is flushed.

+  @retval EFI_UNSUPPORTED   Flush type is not supported.

+  @retval EFI_DEVICE_ERROR  Requested range could not be flushed..

+

+**/

+EFI_STATUS

+EFIAPI

+FlushCpuDataCache (

+  IN EFI_CPU_ARCH_PROTOCOL     *This,

+  IN EFI_PHYSICAL_ADDRESS      Start,

+  IN UINT64                    Length,

+  IN EFI_CPU_FLUSH_TYPE        FlushType

+  );

+

+/**

+  This function enables interrupt processing by the processor.

+

+  This function implements EnableInterrupt() service of CPU Architecture Protocol.

+  This function enables interrupt processing by the processor. This function is

+  used to implement the Boot Services RaiseTPL() and RestoreTPL().

+

+  @param  This              The EFI_CPU_ARCH_PROTOCOL instance.

+

+  @retval EFI_SUCCESS       Interrupts are enabled on the processor.

+  @retval EFI_DEVICE_ERROR  Interrupts could not be enabled on the processor.

+

+**/

+EFI_STATUS

+EFIAPI

+EnableInterrupt (

+  IN EFI_CPU_ARCH_PROTOCOL     *This

+  );

+

+/**

+  This function disables interrupt processing by the processor.

+

+  This function implements DisableInterrupt() service of CPU Architecture Protocol.

+  This function disables interrupt processing by the processor. This function is

+  used to implement the Boot Services RaiseTPL() and RestoreTPL().

+

+  @param  This              The EFI_CPU_ARCH_PROTOCOL instance.

+

+  @retval EFI_SUCCESS       Interrupts are disabled on the processor.

+  @retval EFI_DEVICE_ERROR  Interrupts could not be disabled on the processor.

+

+**/

+EFI_STATUS

+EFIAPI

+DisableInterrupt (

+  IN EFI_CPU_ARCH_PROTOCOL     *This

+  );

+

+/**

+  This function retrieves the processor's current interrupt state.

+

+  This function implements GetInterruptState() service of CPU Architecture Protocol.

+  This function retrieves the processor's current interrupt state.

+

+  @param  This                   The EFI_CPU_ARCH_PROTOCOL instance.

+  @param  State                  A pointer to the processor's current interrupt state.

+                                 Set to TRUE if interrupts are enabled and FALSE if interrupts are disabled.

+

+  @retval EFI_SUCCESS            The processor's current interrupt state was returned in State.

+  @retval EFI_INVALID_PARAMETER  State is NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+GetInterruptStateInstance (

+  IN  EFI_CPU_ARCH_PROTOCOL     *This,

+  OUT BOOLEAN                   *State

+  );

+

+/**

+  This function generates an INIT on the processor.

+

+  This function implements Init() service of CPU Architecture Protocol.

+  This function generates an INIT on the processor.

+

+  @param  This                   The EFI_CPU_ARCH_PROTOCOL instance.

+  @param  InitType               The type of processor INIT to perform.

+

+  @retval EFI_SUCCESS            The processor INIT was performed. This return code should never be seen.

+  @retval EFI_UNSUPPORTED        The processor INIT operation specified by InitType is not supported by this processor.

+  @retval EFI_DEVICE_ERROR       The processor INIT failed.

+

+**/

+EFI_STATUS

+EFIAPI

+Init (

+  IN EFI_CPU_ARCH_PROTOCOL     *This,

+  IN EFI_CPU_INIT_TYPE         InitType

+  );

+

+/**

+  This function Registers a function to be called from the processor interrupt handler.

+

+  This function implements RegisterInterruptHandler() service of CPU Architecture Protocol.

+  This function Registers a function to be called from the processor interrupt handler.

+

+  @param  This                   The EFI_CPU_ARCH_PROTOCOL instance.

+  @param  InterruptType          Defines which interrupt or exception to hook.

+  @param  InterruptHandler       A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER

+                                 that is called when a processor interrupt occurs.

+                                 If this parameter is NULL, then the handler will be uninstalled.

+

+  @retval EFI_SUCCESS            The handler for the processor interrupt was successfully installed or uninstalled.

+  @retval EFI_ALREADY_STARTED    InterruptHandler is not NULL, and a handler for InterruptType was previously installed.

+  @retval EFI_INVALID_PARAMETER  InterruptHandler is NULL, and a handler for InterruptType was not previously installed.

+  @retval EFI_UNSUPPORTED        The interrupt specified by InterruptType is not supported.

+

+**/

+EFI_STATUS

+EFIAPI

+RegisterInterruptHandler (

+  IN EFI_CPU_ARCH_PROTOCOL         *This,

+  IN EFI_EXCEPTION_TYPE            InterruptType,

+  IN EFI_CPU_INTERRUPT_HANDLER     InterruptHandler

+  );

+

+/**

+  This function returns a timer value from one of the processor's internal timers.

+

+  This function implements GetTimerValue() service of CPU Architecture Protocol.

+  This function returns a timer value from one of the processor's internal timers.

+

+  @param  This                   The EFI_CPU_ARCH_PROTOCOL instance.

+  @param  TimerIndex             Specifies which processor timer is to be returned in TimerValue.

+                                 This parameter must be between 0 and EFI_CPU_ARCH_PROTOCOL.NumberOfTimers-1.

+  @param  TimerValue             Pointer to the returned timer value.

+  @param  TimerPeriod            A pointer to the amount of time that passes in femtoseconds for each

+                                 increment of TimerValue. If TimerValue does not increment at a predictable

+                                 rate, then 0 is returned.

+

+  @retval EFI_SUCCESS            The processor timer value specified by TimerIndex was returned in TimerValue.

+  @retval EFI_INVALID_PARAMETER  TimerValue is NULL.

+  @retval EFI_INVALID_PARAMETER  TimerIndex is not valid.

+  @retval EFI_UNSUPPORTEDT       The processor does not have any readable timers.

+  @retval EFI_DEVICE_ERROR       An error occurred attempting to read one of the processor's timers.

+

+**/

+EFI_STATUS

+EFIAPI

+GetTimerValue (

+  IN  EFI_CPU_ARCH_PROTOCOL       *This,

+  IN  UINT32                      TimerIndex,

+  OUT UINT64                      *TimerValue,

+  OUT UINT64                      *TimerPeriod OPTIONAL

+  );

+

+/**

+  This function attempts to set the attributes for a memory range.

+

+  This function implements SetMemoryAttributes() service of CPU Architecture Protocol.

+  This function attempts to set the attributes for a memory range.

+

+  @param  This                   The EFI_CPU_ARCH_PROTOCOL instance.

+  @param  BaseAddress            The physical address that is the start address of a memory region.

+  @param  Length                 The size in bytes of the memory region.

+  @param  Attributes             The bit mask of attributes to set for the memory region.

+

+  @retval EFI_SUCCESS            The attributes were set for the memory region.

+  @retval EFI_INVALID_PARAMETER  Length is zero.

+  @retval EFI_UNSUPPORTED        The processor does not support one or more bytes of the

+                                 memory resource range specified by BaseAddress and Length.

+  @retval EFI_UNSUPPORTED        The bit mask of attributes is not support for the memory resource

+                                 range specified by BaseAddress and Length.

+  @retval EFI_ACCESS_DENIED      The attributes for the memory resource range specified by

+                                 BaseAddress and Length cannot be modified.

+  @retval EFI_OUT_OF_RESOURCES   There are not enough system resources to modify the attributes of

+                                 the memory resource range.

+

+**/

+EFI_STATUS

+EFIAPI

+SetMemoryAttributes (

+  IN EFI_CPU_ARCH_PROTOCOL      *This,

+  IN EFI_PHYSICAL_ADDRESS       BaseAddress,

+  IN UINT64                     Length,

+  IN UINT64                     Attributes

+  );

+

+/**

+  Creates an IDT and a new GDT in RAM.

+  

+  This function creates an IDT and a new GDT in RAM.

+

+**/

+VOID

+InitializeDescriptorTables (

+  VOID

+  );

+

+/**

+  Creates a new GDT in RAM and load it.

+  

+  This function creates a new GDT in RAM and load it.

+

+**/

+VOID

+EFIAPI

+InitializeGdt (

+  VOID

+  );

+

+/**

+  Returns the actual CPU core frequency in MHz.

+

+  This function returns the actual CPU core frequency in MHz.

+

+  @param   Frequency              Pointer to the CPU core frequency.

+  

+  @retval  EFI_SUCCESS            The frequency is returned successfully.

+  @retval  EFI_INVALID_PARAMETER  Frequency is NULL.            

+

+**/

+EFI_STATUS

+GetActualFrequency (

+  OUT UINT64                        *Frequency

+  );

+

+/**

+  Returns the CPU core to processor bus frequency ratio.

+

+  This function returns the CPU core to processor bus frequency ratio.

+

+  @param   Ratio                   Pointer to the CPU core to processor bus frequency ratio.

+

+  @retval  EFI_SUCCESS             The ratio is returned successfully

+  @retval  EFI_UNSUPPORTED         The ratio cannot be measured

+  @retval  EFI_INVALID_PARAMETER   The input parameter is not valid

+

+**/

+EFI_STATUS

+GetCpuBusRatio (

+  OUT UINT32                        *Ratio

+  );

+

+/**

+  Converts the actual frequency in MHz to the standard frequency in MHz.

+

+  This function converts the actual frequency in MHz to the standard frequency in MHz.

+

+  @param   Actual              Actual CPU core frequency.

+  @param   Ratio               CPU core to processor bus frequency ratio.

+  @param   Standard            Standard CPU core frequency.

+

+**/

+VOID

+Actual2StandardFrequency (

+  IN  UINT64                        Actual,

+  IN  UINT32                        Ratio,

+  OUT UINT64                        *Standard

+  );

+

+/**

+  Retrieves the value of CS register.

+

+  This function retrieves the value of CS register.

+

+  @return The value of CS register.

+

+**/

+UINT16

+GetCodeSegment (

+  VOID

+  );

+

+/**

+  Refreshes the GCD Memory Space attributes according to MTRRs.

+  

+  This function refreshes the GCD Memory Space attributes according to MTRRs.

+

+**/

+VOID

+RefreshGcdMemoryAttributes (

+  VOID

+  );

+

+/**

+  Label of base address of IDT vector 0.

+

+  This is just a label of base address of IDT vector 0.

+

+**/

+VOID

+EFIAPI

+AsmIdtVector00 (

+  VOID

+  );

+

+/**

+  Initialize the pointer to the external vector table.

+

+  The external vector table is an array of pointers to C based interrupt/exception

+  callback routines.

+

+  @param VectorTable   The point to the vector table.

+**/

+VOID

+EFIAPI

+InitializeExternalVectorTablePtr(

+  EFI_CPU_INTERRUPT_HANDLER* VectorTable

+  );

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/CpuArchDxe.inf b/IA32FamilyCpuBasePkg/CpuArchDxe/CpuArchDxe.inf
new file mode 100644
index 0000000..d915b1e
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/CpuArchDxe.inf
@@ -0,0 +1,104 @@
+## @file

+# Component description file for CPU Arch DXE Driver.

+#

+# CPU DXE Driver that configures multi-processor environment, logs data to datahub

+#  for processor subclass and cache subclass, and installs CPU Architecture Protocol and MP

+#  Services Protocol

+# Copyright (c) 2013 Intel Corporation.

+#

+# Redistribution and use in source and binary forms, with or without

+# modification, are permitted provided that the following conditions

+# are met:

+#

+# * Redistributions of source code must retain the above copyright

+# notice, this list of conditions and the following disclaimer.

+# * Redistributions in binary form must reproduce the above copyright

+# notice, this list of conditions and the following disclaimer in

+# the documentation and/or other materials provided with the

+# distribution.

+# * Neither the name of Intel Corporation nor the names of its

+# contributors may be used to endorse or promote products derived

+# from this software without specific prior written permission.

+#

+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+#

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = CpuArchDxe

+  FILE_GUID                      = 62D171CB-78CD-4480-8678-C6A2A797A8DE

+  MODULE_TYPE                    = DXE_DRIVER

+  VERSION_STRING                 = 1.0

+  ENTRY_POINT                    = InitializeCpu

+

+#

+# The following information is for reference only and not required by the build tools.

+#

+#  VALID_ARCHITECTURES           = IA32 X64

+#

+#  Create Event Guid C Name:  Event Type: EVENT_TYPE_PERIODIC_TIMER

+#

+#  HOB Guid C Name: gEfiHtBistHobGuid Hob Type: GUID_EXTENSION

+#

+

+[Sources]

+  Cpu.c

+  Cpu.h

+  Exception.h

+  MemoryAttribute.c

+  MemoryAttribute.h

+  MtrrSync.c

+  MtrrSync.h

+

+[Sources.Ia32]

+  IA32/Exception.c

+  IA32/CpuAsm.asm

+  IA32/CpuAsm.S

+  IA32/ArchSpecificDef.h

+  IA32/ArchSpecific.c

+

+[Packages]

+  MdePkg/MdePkg.dec

+  UefiCpuPkg/UefiCpuPkg.dec

+  IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec

+

+[LibraryClasses]

+  MtrrLib

+  TimerLib

+  DxeServicesTableLib

+  IoLib

+  PcdLib

+  UefiBootServicesTableLib

+  MemoryAllocationLib

+  UefiDriverEntryPoint

+  ReportStatusCodeLib

+  BaseMemoryLib

+  DebugLib

+  BaseLib

+  UefiLib

+  LocalApicLib

+  UefiCpuLib

+

+[Protocols]

+  gEfiMpServiceProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED

+  gEfiCpuArchProtocolGuid                       # PROTOCOL ALWAYS_PRODUCED

+

+[Pcd]

+  gEfiCpuTokenSpaceGuid.PcdCpuPageTableAddress

+  gEfiCpuTokenSpaceGuid.PcdCpuMtrrTableAddress

+

+[Depex]

+  TRUE

+

diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/Exception.h b/IA32FamilyCpuBasePkg/CpuArchDxe/Exception.h
new file mode 100644
index 0000000..efba6bc
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/Exception.h
@@ -0,0 +1,137 @@
+/** @file

+

+  Include file for exception handler

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  Exception.h

+

+**/

+#ifndef _CPU_EXCEPTION_H_

+#define _CPU_EXCEPTION_H_

+

+#include <Protocol/DebugSupport.h>

+

+#define INTERRUPT_HANDLER_DIVIDE_ZERO           0x00

+#define INTERRUPT_HANDLER_DEBUG                 0x01

+#define INTERRUPT_HANDLER_NMI                   0x02

+#define INTERRUPT_HANDLER_BREAKPOINT            0x03

+#define INTERRUPT_HANDLER_OVERFLOW              0x04

+#define INTERRUPT_HANDLER_BOUND                 0x05

+#define INTERRUPT_HANDLER_INVALID_OPCODE        0x06

+#define INTERRUPT_HANDLER_DEVICE_NOT_AVAILABLE  0x07

+#define INTERRUPT_HANDLER_TIMER                 0x08

+#define INTERRUPT_HANDLER_COPROCESSOR_OVERRUN   0x09

+#define INTERRUPT_HANDLER_INVALID_TSS           0x0A

+#define INTERRUPT_HANDLER_SEGMENT_NOT_PRESENT   0x0B

+#define INTERRUPT_HANDLER_STACK_SEGMENT_FAULT   0x0C

+#define INTERRUPT_HANDLER_GP_FAULT              0x0D

+#define INTERRUPT_HANDLER_PAGE_FAULT            0x0E

+#define INTERRUPT_HANDLER_RESERVED              0x0F

+#define INTERRUPT_HANDLER_MATH_FAULT            0x10

+#define INTERRUPT_HANDLER_ALIGNMENT_FAULT       0x11

+#define INTERRUPT_HANDLER_MACHINE_CHECK         0x12

+#define INTERRUPT_HANDLER_STREAMING_SIMD        0x13

+

+//

+// Register Structure Definitions

+//

+typedef union {

+  EFI_SYSTEM_CONTEXT_IA32 SystemContextIa32;

+  EFI_SYSTEM_CONTEXT_X64  SystemContextX64;

+} SYSTEM_CONTEXT;

+

+//

+// Register Structure Definitions

+//

+typedef struct {

+  EFI_STATUS_CODE_DATA    Header;

+  SYSTEM_CONTEXT          SystemContext;

+} CPU_STATUS_CODE_TEMPLATE;

+

+typedef struct {

+  UINT32        ErrorMessage;

+  UINT8         Interrupt;

+} EFI_EXCEPTION_HANDLER;

+

+/**

+  The sample exception handler.

+

+  This function is called by primitive interrupt handler in assembly code, and

+  parameters of InterruptType and SystemContext are prepared by it beforehand.

+  This function outputs context of all registers when exception occurs. It then

+  reports status code for the exception.

+

+  @param  InterruptType  Exception type.

+  @param  SystemContext  System context data.

+

+**/

+VOID

+EFIAPI

+CommonExceptionHandler (

+  IN EFI_EXCEPTION_TYPE   InterruptType,

+  IN EFI_SYSTEM_CONTEXT   SystemContext

+  );

+

+/**

+  Installs the Exception Handler.

+

+  This function installs the Exception Handler.

+

+  @param  ExceptionBegin   The begin number of exception

+

+**/

+VOID

+InitializeException (

+  IN UINT32              ExceptionBegin         

+  );

+

+/**

+  Set Interrupt Descriptor Table Handler Address.

+

+  @param Index        The Index of the interrupt descriptor table handle.

+

+**/

+VOID

+SetInterruptDescriptorTableHandlerAddress (

+  IN UINTN       Index

+  );

+

+/**

+  Restore original Interrupt Descriptor Table Handler Address.

+

+  @param Index        The Index of the interrupt descriptor table handle.

+

+**/

+VOID

+RestoreInterruptDescriptorTableHandlerAddress (

+  IN UINTN       Index

+  );

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecific.c b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecific.c
new file mode 100644
index 0000000..bb21274
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecific.c
@@ -0,0 +1,177 @@
+/** @file

+

+  Memory Operation Functions for IA32 Architecture.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  ArchSpecific.c

+

+**/

+

+#include "Cpu.h"

+#include "MemoryAttribute.h"

+

+extern EFI_CPU_INTERRUPT_HANDLER   mExternalVectorTable[];

+

+INTERRUPT_HANDLER_TEMPLATE_MAP mTemplateMap;

+INTERRUPT_GATE_DESCRIPTOR      *mIdtTable = NULL;

+VOID                           *mInterruptHandler = NULL;

+INTERRUPT_GATE_DESCRIPTOR      *mOrigIdtEntry = NULL;

+UINT16                         mOrigIdtEntryCount = 0;

+

+UINT64   mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;

+UINT64   mValidMtrrBitsMask    = MTRR_LIB_MSR_VALID_MASK;

+

+/**

+  Creates an IDT and a new GDT in RAM.

+

+  This function creates an IDT and a new GDT in RAM.

+

+**/

+VOID

+InitializeDescriptorTables (

+  VOID

+  )

+{

+  UINT16                          CodeSegment;

+  INTERRUPT_GATE_DESCRIPTOR       *IdtEntry;

+  UINTN                           Index;

+  INTERRUPT_GATE_DESCRIPTOR       *IdtTable;

+  UINT8                           *InterruptHandler;

+  IA32_DESCRIPTOR                 Idtr;

+

+  //

+  // Load Global Descriptor Table and update segment selectors

+  //

+  InitializeGdt ();

+

+  //

+  // Create Interrupt Descriptor Table

+  //

+  IdtTable = AllocateZeroPool (sizeof (INTERRUPT_GATE_DESCRIPTOR) * INTERRUPT_VECTOR_NUMBER);

+

+  GetTemplateAddressMap (&mTemplateMap);

+  InterruptHandler  = AllocatePool (mTemplateMap.Size * INTERRUPT_VECTOR_NUMBER);

+

+  CodeSegment       = AsmReadCs ();

+

+  //

+  // Get original IDT address and size and save original IDT entry.

+  //

+  AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);

+  mOrigIdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (INTERRUPT_GATE_DESCRIPTOR));

+  ASSERT (mOrigIdtEntryCount <= INTERRUPT_VECTOR_NUMBER);

+  mOrigIdtEntry = AllocateCopyPool (Idtr.Limit + 1, (VOID *) Idtr.Base);

+  ASSERT (mOrigIdtEntry != NULL);

+

+  //

+  // Copy original IDT entry.

+  //

+  IdtEntry = IdtTable;

+  CopyMem (IdtEntry, (VOID *) Idtr.Base, Idtr.Limit + 1);

+

+  //

+  // Save IDT table pointer and Interrupt table pointer

+  //

+  mIdtTable         = IdtTable;

+  mInterruptHandler = InterruptHandler;

+

+  for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++) {

+    //

+    // Update all IDT entries to use current CS value.

+    //

+    IdtEntry[Index].SegmentSelector = CodeSegment;

+    if (Index < mOrigIdtEntryCount) {

+      //

+      // Skip original IDT entry.

+      //

+      continue;

+    }

+    //

+    // Set the address of interrupt handler to the rest IDT entry.

+    //

+    SetInterruptDescriptorTableHandlerAddress (Index);

+  }

+

+  InitializeIdt (

+    &(mExternalVectorTable[0]),

+    (UINTN *) IdtTable,

+    (UINT16) (sizeof (INTERRUPT_GATE_DESCRIPTOR) * INTERRUPT_VECTOR_NUMBER)

+    );

+

+  //

+  // Initialize Exception Handlers

+  //

+  InitializeException (mOrigIdtEntryCount);

+}

+

+/**

+  Set Interrupt Descriptor Table Handler Address.

+

+  @param Index        The Index of the interrupt descriptor table handle.

+

+**/

+VOID

+SetInterruptDescriptorTableHandlerAddress (

+  IN UINTN       Index

+  )

+{

+  UINTN          ExceptionHandle;

+

+  //

+  // Get the address of handler for entry

+  //

+  ExceptionHandle = (UINTN)mInterruptHandler + Index * mTemplateMap.Size;

+  CopyMem ((VOID *)ExceptionHandle, mTemplateMap.Start, mTemplateMap.Size);

+  *(UINT32 *) (ExceptionHandle + mTemplateMap.FixOffset) = Index;

+

+  mIdtTable[Index].OffsetLow  = (UINT16) ExceptionHandle;

+  mIdtTable[Index].Attributes = INTERRUPT_GATE_ATTRIBUTE;

+  //

+  // 8e00;

+  //

+  mIdtTable[Index].OffsetHigh = (UINT16) (ExceptionHandle >> 16);

+}

+

+/**

+  Restore original Interrupt Descriptor Table Handler Address.

+

+  @param Index        The Index of the interrupt descriptor table handle.

+

+**/

+VOID

+RestoreInterruptDescriptorTableHandlerAddress (

+  IN UINTN       Index

+  )

+{

+  if (Index < mOrigIdtEntryCount) {

+    mIdtTable[Index].OffsetLow  = mOrigIdtEntry[Index].OffsetLow;

+    mIdtTable[Index].OffsetHigh = mOrigIdtEntry[Index].OffsetHigh;

+  }

+}

diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecificDef.h b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecificDef.h
new file mode 100644
index 0000000..e0f20fd
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/ArchSpecificDef.h
@@ -0,0 +1,99 @@
+/** @file

+

+Copyright (c) 2013 Intel Corporation.

+

+Redistribution and use in source and binary forms, with or without

+modification, are permitted provided that the following conditions

+are met:

+

+* Redistributions of source code must retain the above copyright

+notice, this list of conditions and the following disclaimer.

+* Redistributions in binary form must reproduce the above copyright

+notice, this list of conditions and the following disclaimer in

+the documentation and/or other materials provided with the

+distribution.

+* Neither the name of Intel Corporation nor the names of its

+contributors may be used to endorse or promote products derived

+from this software without specific prior written permission.

+

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+

+Module Name:

+

+  ProcessorDef.h

+

+Abstract:

+

+  Definition for IA32 processor

+

+**/

+

+#ifndef _PROCESSOR_DEF_H_

+#define _PROCESSOR_DEF_H_

+

+#include <Protocol/Cpu.h>

+

+#pragma pack(1)

+

+typedef struct {

+  UINT16  OffsetLow;

+  UINT16  SegmentSelector;

+  UINT16  Attributes;

+  UINT16  OffsetHigh;

+} INTERRUPT_GATE_DESCRIPTOR;

+

+#pragma pack()

+

+typedef struct {

+  VOID  *Start;

+  UINTN Size;

+  UINTN FixOffset;

+} INTERRUPT_HANDLER_TEMPLATE_MAP;

+

+/**

+  Return address map of interrupt handler template so that C code can generate

+  interrupt handlers, and dynamically do address fix.

+

+  @param AddressMap  Pointer to a buffer where the address map is returned.

+**/

+VOID

+EFIAPI

+GetTemplateAddressMap (

+  OUT INTERRUPT_HANDLER_TEMPLATE_MAP *AddressMap

+  );

+

+/**

+  Creates an IDT table starting at IdtTablPtr. It has IdtLimit/8 entries.

+  Table is initialized to intxx where xx is from 00 to number of entries or

+  100h, whichever is smaller. After table has been initialized the LIDT

+  instruction is invoked.

+ 

+  TableStart is the pointer to the callback table and is not used by 

+  InitializedIdt but by commonEntry. CommonEntry handles all interrupts,

+  does the context save and calls the callback entry, if non-NULL.

+  It is the responsibility of the callback routine to do hardware EOIs.

+

+  @param TableStart     Pointer to interrupt callback table.

+  @param IdtTablePtr    Pointer to IDT table.

+  @param IdtTableLimit  IDT Table limit (number of interrupt entries * 8).

+**/

+VOID

+EFIAPI

+InitializeIdt (

+  IN EFI_CPU_INTERRUPT_HANDLER      *TableStart,

+  IN UINTN                          *IdtTablePtr,

+  IN UINT16                         IdtTableLimit

+  );

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.S b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.S
new file mode 100644
index 0000000..8dfdbdc
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.S
@@ -0,0 +1,574 @@
+#------------------------------------------------------------------------------

+#

+# Copyright (c) 2013 Intel Corporation.

+#

+# Redistribution and use in source and binary forms, with or without

+# modification, are permitted provided that the following conditions

+# are met:

+#

+# * Redistributions of source code must retain the above copyright

+# notice, this list of conditions and the following disclaimer.

+# * Redistributions in binary form must reproduce the above copyright

+# notice, this list of conditions and the following disclaimer in

+# the documentation and/or other materials provided with the

+# distribution.

+# * Neither the name of Intel Corporation nor the names of its

+# contributors may be used to endorse or promote products derived

+# from this software without specific prior written permission.

+#

+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+#

+# Module Name:

+#

+#   CpuAsm.S

+# 

+# Abstract:

+# 

+#   Assembly code that supports IA32 CPU architectural protocol

+#

+#------------------------------------------------------------------------------

+

+.data

+

+ExternalVectorTablePtr:            .space  4

+CommonInterruptEntry:              .long   CommonEntry

+Idtr:                              .space  2

+Idtr1:                             .space  4

+

+.text

+

+#---------------------------------------;

+# _InitializeIdt                ;

+#----------------------------------------------------------------------------;

+# 

+# Protocol prototype

+#   InitializeIdt (

+#   IN EFI_CPU_INTERRUPT_HANDLER TableStart,

+#   IN UINTN                     *IdtTablePtr,

+#   IN UINT16                    IdtLimit

+#   )

+#           

+# Routine Description:

+# 

+#  Creates an IDT table starting at IdtTablPtr. It has IdtLimit/8 entries.

+#  Table is initialized to intxx where xx is from 00 to number of entries or

+#  100h, whichever is smaller. After table has been initialized the LIDT

+#  instruction is invoked.

+# 

+#  TableStart is the pointer to the callback table and is not used by 

+#  InitializedIdt but by commonEntry. CommonEntry handles all interrupts,

+#  does the context save and calls the callback entry, if non-NULL.

+#  It is the responsibility of the callback routine to do hardware EOIs.

+# 

+# Arguments:

+# 

+#   TableStart          - Pointer to interrupt callback table

+#

+#   IdtTablePtr         - Pointer to IDT table

+#

+#   IdtLimit            - IDT Table limit = number of interrupt entries * 8

+# 

+# Returns: 

+# 

+#   Nothing

+#

+# 

+# Input:  [ebp][0]  = Original ebp

+#         [ebp][4]  = Return address

+#         [ebp][8]  = TableStart

+#         [ebp][0c] = *IdtTablePtr

+#         [ebp][10] = IdtLimit

+#          

+# Output: Nothing

+#           

+# Destroys: Nothing

+#-----------------------------------------------------------------------------;

+

+ASM_GLOBAL ASM_PFX(InitializeIdt)

+ASM_PFX(InitializeIdt):

+  pushl   %ebp              # C prolog

+  movl    %esp,%ebp

+  pushl   %edi

+

+  movl    8(%ebp),%eax                  # Get ExternalVectorTable Address

+  movl    %eax, ExternalVectorTablePtr

+

+  movw    0x10(%ebp),%ax                # Get IDT Table limit

+  decw    %ax

+  movw    %ax, Idtr

+

+  movl    0xc(%ebp),%eax                # Get Start of IDT

+  movl    %eax, Idtr1

+

+  movl    $Idtr, %edi

+  lidt    %es:(%edi)

+

+  popl    %edi

+  popl    %ebp

+  ret

+

+#----------------------------------------------------------------------------;

+# 

+# Protocol prototype

+#   None

+#           

+# Routine Description:

+# 

+#  These routines handle the individual interrupts. These routines always

+#  gain control on any interrupt or exception. They save EAX and place

+#  the interrupt number in EAX. CommonEntry is then jumped to. 

+#  instruction is invoked.

+# 

+#  CommonEntry handles all interrupts,does the context save and calls the 

+#  callback entry, if non-NULL. It is the responsibility of the callback 

+#  routine to do hardware EOIs. Callbacks are entered into the table

+#  located at TableStart. Entries are modified by the InstallInterruptHandler

+#  and UninstallInterruptHandler protocols.

+# 

+# Arguments to CommonEntry:

+# 

+#   EAX                 - Interrupt or exception number

+#

+#   TableStart          - Pointer to interrupt callback table

+# 

+# Returns: 

+# 

+#   Nothing

+#

+# 

+# Output: Nothing

+#           

+# Destroys: Nothing

+#-----------------------------------------------------------------------------;

+

+TemplateStart: 

+   pushl %eax

+

+   #mov  eax, 0nnh (nn stands for vector number, which will be fixed at runtime 

+   .byte 0xb8

+VectorNumber:   

+   .long 0x0

+

+   jmp  *CommonInterruptEntry

+TemplateEnd: 

+

+CommonEntry: 

+

+#---------------------------------------;

+# _CommonEntry                  ;

+#----------------------------------------------------------------------------;

+# The follow algorithm is used for the common interrupt routine.

+# Entry from each interrupt with a push eax and eax=interrupt number

+

+#

+# +---------------------+

+# +    EFlags           +

+# +---------------------+

+# +    CS               +

+# +---------------------+

+# +    EIP              +

+# +---------------------+

+# +    Error Code       +

+# +---------------------+

+# + EAX / Vector Number +

+# +---------------------+

+# +    EBP              +

+# +---------------------+ <-- EBP

+#

+

+  cli

+  #

+  # All interrupt handlers are invoked through interrupt gates, so

+  # IF flag automatically cleared at the entry point

+  #

+  cmpl    $32,%eax        # Intel reserved vector for exceptions?

+  jae     NoErrorCode

+  btl     %eax, %cs:ASM_PFX(mErrorCodeFlag)

+  jc      L1

+

+NoErrorCode: 

+  #

+  # Push a dummy error code on the stack

+  # to maintain coherent stack map

+  #

+  pushl   (%esp)

+  movl    $0, 4(%esp)

+L1:

+  pushl   %ebp

+  movl    %esp,%ebp

+

+  #

+  # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32

+  # is 16-byte aligned

+  #

+  andl    $0xfffffff0,%esp

+  subl    $12,%esp

+

+## UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;

+  pushl   0x4(%ebp)

+  pushl   %ecx

+  pushl   %edx

+  pushl   %ebx

+  leal    24(%ebp),%ecx

+  pushl   %ecx                         # ESP

+  pushl   (%ebp)

+  pushl   %esi

+  pushl   %edi

+

+  movl    %eax,4(%ebp)                 # save vector number

+

+## UINT32  Gs, Fs, Es, Ds, Cs, Ss;

+  movl %ss,%eax

+  pushl %eax

+  movzwl 0x10(%ebp), %eax

+  pushl %eax

+  movl %ds,%eax

+  pushl %eax

+  movl %es,%eax

+  pushl %eax

+  movl %fs,%eax

+  pushl %eax

+  movl %gs,%eax

+  pushl %eax

+

+## UINT32  Eip;

+  pushl    12(%ebp)

+

+## UINT32  Gdtr[2], Idtr[2];

+  subl $8,%esp

+  sidt (%esp)

+  subl $8,%esp

+  sgdt (%esp)

+

+## UINT32  Ldtr, Tr;

+  xorl %eax,%eax

+  strl %eax

+  pushl %eax

+  sldtl %eax

+  pushl %eax

+

+## UINT32  EFlags;

+  pushl    20(%ebp)

+

+## UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;

+  movl %cr4, %eax

+  pushl %eax

+  movl %cr3, %eax

+  pushl %eax

+  movl %cr2, %eax

+  pushl %eax

+  xorl %eax,%eax

+  pushl %eax

+  movl %cr0, %eax

+  pushl %eax

+

+## UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;

+  movl    %dr7, %eax

+  pushl   %eax

+  movl    %dr6, %eax

+  pushl   %eax

+  movl    %dr3, %eax

+  pushl   %eax

+  movl    %dr2, %eax

+  pushl   %eax

+  movl    %dr1, %eax

+  pushl   %eax

+  movl    %dr0, %eax

+  pushl   %eax

+

+## UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear

+  cld

+

+## UINT32  ExceptionData;

+  pushl   8(%ebp)

+

+## call into exception handler

+  movl    4(%ebp),%ebx

+  movl    ExternalVectorTablePtr, %eax

+  movl    (%eax,%ebx,4),%eax

+  orl     %eax,%eax               # NULL?

+  je  nonNullValue #

+

+## Prepare parameter and call

+  movl    %esp,%edx

+  pushl   %edx

+  pushl   %ebx

+  call    *%eax

+  addl    $8,%esp

+

+nonNullValue: 

+  cli

+## UINT32  ExceptionData;

+  addl $4,%esp

+

+## UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;

+## Skip restoration of DRx registers to support in-circuit emualators

+## or debuggers set breakpoint in interrupt/exception context

+  addl    $24, %esp

+

+## UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;

+  popl    %eax

+  movl    %eax, %cr0

+  addl    $4,%esp   # not for Cr1

+  popl    %eax

+  movl    %eax, %cr2

+  popl    %eax

+  movl    %eax, %cr3

+  popl    %eax

+  movl    %eax, %cr4

+

+## UINT32  EFlags;

+  popl    20(%ebp)

+

+## UINT32  Ldtr, Tr;

+## UINT32  Gdtr[2], Idtr[2];

+## Best not let anyone mess with these particular registers...

+  addl    $24,%esp

+

+## UINT32  Eip;

+   pop     12(%ebp)

+

+## UINT32  Gs, Fs, Es, Ds, Cs, Ss;

+## NOTE - modified segment registers could hang the debugger...  We

+##        could attempt to insulate ourselves against this possibility,

+##        but that poses risks as well.

+##

+  popl    %gs

+  popl    %fs

+  popl    %es

+  popl    %ds

+  popl    16(%ebp)

+  popl    %ss

+

+## UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;

+  popl    %edi

+  popl    %esi

+  addl    $4,%esp  # not for ebp

+  addl    $4,%esp  # not for esp

+  popl    %ebx

+  popl    %edx

+  popl    %ecx

+  popl    %eax

+

+  movl    %ebp,%esp

+  popl    %ebp

+  addl    $8,%esp

+  iretl

+

+

+#---------------------------------------;

+# _GetTemplateAddressMap                  ;

+#----------------------------------------------------------------------------;

+# 

+# Protocol prototype

+#   GetTemplateAddressMap (

+#     INTERRUPT_HANDLER_TEMPLATE_MAP *AddressMap

+#   );

+#           

+# Routine Description:

+# 

+#  Return address map of interrupt handler template so that C code can generate

+#  interrupt handlers, and dynamically do address fix.

+# 

+# Arguments:

+# 

+# 

+# Returns: 

+# 

+#   Nothing

+#

+# 

+# Input:  [ebp][0]  = Original ebp

+#         [ebp][4]  = Return address

+#          

+# Output: Nothing

+#           

+# Destroys: Nothing

+#-----------------------------------------------------------------------------;

+ASM_GLOBAL ASM_PFX(GetTemplateAddressMap)

+ASM_PFX(GetTemplateAddressMap):

+  pushl   %ebp                # C prolog

+  movl    %esp,%ebp

+  pushal

+

+  movl 8(%ebp), %ebx

+  movl $TemplateStart, (%ebx)

+  movl $(TemplateEnd - TemplateStart), 4(%ebx)

+

+  # Note: if code in Template is updated, the value fills into the 3rd parameter 

+  # also needs update

+  movl $(VectorNumber - TemplateStart), 8(%ebx)

+

+  popal

+  popl    %ebp

+  ret

+

+

+

+#---------------------------------------;

+# _InitializeSelectors                  ;

+#----------------------------------------------------------------------------;

+# 

+# Protocol prototype

+#   InitializeSelectors (

+#   )

+#           

+# Routine Description:

+# 

+#  Creates an new GDT in RAM.  The problem is that our former selectors

+#  were ROM based and the EFI OS Loader does not manipulate the machine state 

+#  to change them (as it would for a 16-bit PC/AT startup code that had to

+#  go from Real Mode to flat mode).

+# 

+# Arguments:

+# 

+# 

+# Returns: 

+# 

+#   Nothing

+#

+# 

+# Input:  [ebp][0]  = Original ebp

+#         [ebp][4]  = Return address

+#          

+# Output: Nothing

+#           

+# Destroys: Nothing

+#-----------------------------------------------------------------------------;

+

+.equ          CODE_SELECTOR, 0x10

+.equ          DATA_SELECTOR, 0x18

+

+ASM_GLOBAL ASM_PFX(InitializeGdt)

+ASM_PFX(InitializeGdt):

+  pushl   %ebp                # C prolog

+  movl    %esp,%ebp

+  pushal

+  movl    $Gdtr, %edi

+

+  movw    %cs,%ax             # Get the selector data from our code image          

+  .byte 0x66

+  movw    %ax,%es

+  lgdt    %es:(%edi)

+

+  .byte 0x67

+  .byte 0xea                # Far Jump Offset:Selector to reload CS

+  .long      SelectorRld

+  .word      CODE_SELECTOR

+SelectorRld:

+  movw    $DATA_SELECTOR, %ax # Update the Base for the new selectors, too

+  .byte 0x66

+  movw    %ax,%ds

+  .byte 0x66

+  movw    %ax,%es

+  .byte 0x66

+  movw    %ax,%fs

+  .byte 0x66

+  movw    %ax,%gs

+  .byte 0x66

+  movw    %ax,%ss

+

+  popal

+  popl    %ebp

+  ret

+

+#-----------------------------------------------------------------------------;

+# data

+#-----------------------------------------------------------------------------;

+

+        .p2align 4

+

+Gdtr:    .word GDT_END - GDT_BASE - 1

+         .long GDT_BASE

+

+#-----------------------------------------------------------------------------;

+#   global descriptor table (GDT)

+#-----------------------------------------------------------------------------;

+

+        .p2align 4

+

+GDT_BASE: 

+# null descriptor

+# .equ                NULL_SEL, $-GDT_BASE # Selector [0]

+        .word 0         # limit 15:0

+        .word 0         # base 15:0

+        .byte 0         # base 23:16

+        .byte 0         # type

+        .byte 0         # limit 19:16, flags

+        .byte 0         # base 31:24

+

+# linear data segment descriptor

+# .equ            LINEAR_SEL, $-GDT_BASE # Selector [0x8]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# linear code segment descriptor

+# .equ            LINEAR_CODE_SEL, $-GDT_BASE # Selector [0x10]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# system data segment descriptor

+# .equ            SYS_DATA_SEL, $-GDT_BASE # Selector [0x18]

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x92      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# system code segment descriptor

+# .equ            SYS_CODE_SEL, $-GDT_BASE

+        .word 0xFFFF    # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0x9A      # present, ring 0, data, expand-up, writable

+        .byte 0xCF              # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+# .equ        SPARE3_SEL, $-GDT_BASE

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+# .equ        SPARE4_SEL, $-GDT_BASE

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+# spare segment descriptor

+# .equ        SPARE5_SEL, $-GDT_BASE

+        .word 0         # limit 0xFFFFF

+        .word 0         # base 0

+        .byte 0

+        .byte 0         # present, ring 0, data, expand-up, writable

+        .byte 0         # page-granular, 32-bit

+        .byte 0

+

+GDT_END: 

+

diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.asm b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.asm
new file mode 100644
index 0000000..bce50c6
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/CpuAsm.asm
@@ -0,0 +1,588 @@
+  page    ,132

+  title   CPU ARCHITECTURAL DXE PROTOCOL ASSEMBLY HOOKS

+;------------------------------------------------------------------------------

+;

+; Copyright (c) 2013 Intel Corporation.

+;

+; Redistribution and use in source and binary forms, with or without

+; modification, are permitted provided that the following conditions

+; are met:

+;

+; * Redistributions of source code must retain the above copyright

+; notice, this list of conditions and the following disclaimer.

+; * Redistributions in binary form must reproduce the above copyright

+; notice, this list of conditions and the following disclaimer in

+; the documentation and/or other materials provided with the

+; distribution.

+; * Neither the name of Intel Corporation nor the names of its

+; contributors may be used to endorse or promote products derived

+; from this software without specific prior written permission.

+;

+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+;

+; Module Name:

+;

+;   CpuAsm.asm

+; 

+; Abstract:

+; 

+;   Assembly code that supports IA32 CPU architectural protocol

+;

+;------------------------------------------------------------------------------

+

+.686p

+.model  flat        

+

+.data

+ExternalVectorTablePtr DD ?             ; Table of call backs

+CommonInterruptEntry   DD CommonEntry   ; Address of CommonEntry

+Idtr                   DW ?             ; FWORD for IDT register

+Idtr1                  DD ?             ; MUST BE IMMEDIATELY AFTER Idtr

+

+EXTRN _mErrorCodeFlag:DWORD             ; Error code flags for exceptions

+

+.stack

+.code

+.MMX

+.XMM

+

+UINT8    TYPEDEF    BYTE

+UINT16   TYPEDEF    WORD

+UINT32   TYPEDEF    DWORD

+UINT64   TYPEDEF    QWORD

+UINTN    TYPEDEF    UINT32

+

+;---------------------------------------;

+; _InitializeIdt                ;

+;----------------------------------------------------------------------------;

+; 

+; Protocol prototype

+;   InitializeIdt (

+;   IN EFI_CPU_INTERRUPT_HANDLER TableStart,

+;   IN UINTN                     *IdtTablePtr,

+;   IN UINT16                    IdtLimit

+;   )

+;           

+; Routine Description:

+; 

+;  Creates an IDT table starting at IdtTablPtr. It has IdtLimit/8 entries.

+;  Table is initialized to intxx where xx is from 00 to number of entries or

+;  100h, whichever is smaller. After table has been initialized the LIDT

+;  instruction is invoked.

+; 

+;  TableStart is the pointer to the callback table and is not used by 

+;  InitializedIdt but by commonEntry. CommonEntry handles all interrupts,

+;  does the context save and calls the callback entry, if non-NULL.

+;  It is the responsibility of the callback routine to do hardware EOIs.

+; 

+; Arguments:

+; 

+;   TableStart          - Pointer to interrupt callback table

+;

+;   IdtTablePtr         - Pointer to IDT table

+;

+;   IdtLimit            - IDT Table limit = number of interrupt entries * 8

+; 

+; Returns: 

+; 

+;   Nothing

+;

+; 

+; Input:  [ebp][0]  = Original ebp

+;         [ebp][4]  = Return address

+;         [ebp][8]  = TableStart

+;         [ebp][0c] = *IdtTablePtr

+;         [ebp][10] = IdtLimit

+;          

+; Output: Nothing

+;           

+; Destroys: Nothing

+;-----------------------------------------------------------------------------;

+

+_InitializeIdt  proc near public

+  push    ebp               ; C prolog

+  mov     ebp, esp

+  push    edi

+

+  mov     eax, [ebp+8]                  ; Get ExternalVectorTable Address

+  mov     ExternalVectorTablePtr, eax

+

+  mov     ax, [ebp+10h]                 ; Get IDT Table limit

+  dec     ax

+  mov     Idtr, ax

+

+  mov     eax, [ebp+0ch]                ; Get Start of IDT

+  mov     Idtr1, eax

+  

+  mov     edi, OFFSET Idtr              ; Load IDT register

+  lidt    FWORD PTR es:[edi]

+

+  pop     edi

+  pop     ebp

+  ret

+_InitializeIdt  endp

+

+;----------------------------------------------------------------------------;

+; 

+; Protocol prototype

+;   None

+;           

+; Routine Description:

+; 

+;  These routines handle the individual interrupts. These routines always

+;  gain control on any interrupt or exception. They save EAX and place

+;  the interrupt number in EAX. CommonEntry is then jumped to. 

+;  instruction is invoked.

+; 

+;  CommonEntry handles all interrupts,does the context save and calls the 

+;  callback entry, if non-NULL. It is the responsibility of the callback 

+;  routine to do hardware EOIs. Callbacks are entered into the table

+;  located at TableStart. Entries are modified by the InstallInterruptHandler

+;  and UninstallInterruptHandler protocols.

+; 

+; Arguments to CommonEntry:

+; 

+;   EAX                 - Interrupt or exception number

+;

+;   TableStart          - Pointer to interrupt callback table

+; 

+; Returns: 

+; 

+;   Nothing

+;

+; 

+; Output: Nothing

+;           

+; Destroys: Nothing

+;-----------------------------------------------------------------------------;

+

+TemplateStart:

+   push eax

+   

+   ;mov  eax, 0nnh (nn stands for vector number, which will be fixed at runtime 

+   DB   0b8h

+VectorNumber:   

+   DD   00h

+

+   jmp  dword ptr [CommonInterruptEntry];

+TemplateEnd:

+

+CommonEntry:

+

+;---------------------------------------;

+; _CommonEntry                  ;

+;----------------------------------------------------------------------------;

+; The follow algorithm is used for the common interrupt routine.

+; Entry from each interrupt with a push eax and eax=interrupt number

+

+;

+; +---------------------+

+; +    EFlags           +

+; +---------------------+

+; +    CS               +

+; +---------------------+

+; +    EIP              +

+; +---------------------+

+; +    Error Code       +

+; +---------------------+

+; + EAX / Vector Number +

+; +---------------------+

+; +    EBP              +

+; +---------------------+ <-- EBP

+;

+

+  cli

+  ;

+  ; All interrupt handlers are invoked through interrupt gates, so

+  ; IF flag automatically cleared at the entry point

+  ;

+  cmp     eax, 32         ; Intel reserved vector for exceptions?

+  jae     NoErrorCode

+  bt      cs:_mErrorCodeFlag, eax

+  jc      @F

+

+NoErrorCode:

+  ;

+  ; Push a dummy error code on the stack

+  ; to maintain coherent stack map

+  ;

+  push    [esp]

+  mov     dword ptr [esp + 4], 0

+@@:       

+  push    ebp

+  mov     ebp, esp

+

+  ;

+  ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32

+  ; is 16-byte aligned

+  ;

+  and     esp, 0fffffff0h

+  sub     esp, 12

+

+;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;

+  push    dword ptr [ebp + 4]          ; EAX

+  push    ecx

+  push    edx

+  push    ebx

+  lea     ecx, [ebp + 24]

+  push    ecx                          ; ESP

+  push    dword ptr [ebp]              ; EBP

+  push    esi

+  push    edi

+

+  mov     [ebp + 4], eax               ; save vector number

+

+;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;

+  mov  eax, ss

+  push eax

+  movzx eax, word ptr [ebp + 16]

+  push eax

+  mov  eax, ds

+  push eax

+  mov  eax, es

+  push eax

+  mov  eax, fs

+  push eax

+  mov  eax, gs

+  push eax

+

+;; UINT32  Eip;

+  push    dword ptr [ebp + 12]

+

+;; UINT32  Gdtr[2], Idtr[2];

+  sub  esp, 8

+  sidt fword ptr [esp]

+  sub  esp, 8

+  sgdt fword ptr [esp]

+

+;; UINT32  Ldtr, Tr;

+  xor  eax, eax

+  str  ax

+  push eax

+  sldt ax

+  push eax

+

+;; UINT32  EFlags;

+  push    dword ptr [ebp + 20]

+

+;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;

+  mov  eax, cr4

+  push eax

+  mov  eax, cr3

+  push eax

+  mov  eax, cr2

+  push eax

+  xor  eax, eax

+  push eax

+  mov  eax, cr0

+  push eax

+

+;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;

+  mov     eax, dr7

+  push    eax

+  mov     eax, dr6

+  push    eax

+  mov     eax, dr3

+  push    eax

+  mov     eax, dr2

+  push    eax

+  mov     eax, dr1

+  push    eax

+  mov     eax, dr0

+  push    eax

+

+;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear

+  cld

+

+;; UINT32  ExceptionData;

+  push    dword ptr [ebp + 8]

+

+;; call into exception handler

+  mov     ebx, [ebp + 4]

+  mov     eax, ExternalVectorTablePtr

+  mov     eax, [eax + ebx * 4]

+  or      eax, eax                ; NULL?

+  je  nonNullValue;

+

+;; Prepare parameter and call

+  mov     edx, esp

+  push    edx

+  push    ebx

+  call    eax

+  add     esp, 8

+

+nonNullValue:

+  cli

+;; UINT32  ExceptionData;

+  add esp, 4

+

+;; UINT32  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;

+;; Skip restoration of DRx registers to support in-circuit emualators

+;; or debuggers set breakpoint in interrupt/exception context

+  add     esp, 4 * 6

+

+;; UINT32  Cr0, Cr1, Cr2, Cr3, Cr4;

+  pop     eax

+  mov     cr0, eax

+  add     esp, 4    ; not for Cr1

+  pop     eax

+  mov     cr2, eax

+  pop     eax

+  mov     cr3, eax

+  pop     eax

+  mov     cr4, eax

+

+;; UINT32  EFlags;

+  pop     dword ptr [ebp + 20]

+

+;; UINT32  Ldtr, Tr;

+;; UINT32  Gdtr[2], Idtr[2];

+;; Best not let anyone mess with these particular registers...

+  add     esp, 24

+

+;; UINT32  Eip;

+  pop     dword ptr [ebp + 12]

+

+;; UINT32  Gs, Fs, Es, Ds, Cs, Ss;

+;; NOTE - modified segment registers could hang the debugger...  We

+;;        could attempt to insulate ourselves against this possibility,

+;;        but that poses risks as well.

+;;

+  pop     gs

+  pop     fs

+  pop     es

+  pop     ds

+  pop     dword ptr [ebp + 16]

+  pop     ss

+

+;; UINT32  Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;

+  pop     edi

+  pop     esi

+  add     esp, 4   ; not for ebp

+  add     esp, 4   ; not for esp

+  pop     ebx

+  pop     edx

+  pop     ecx

+  pop     eax

+

+  mov     esp, ebp

+  pop     ebp

+  add     esp, 8

+  iretd

+

+

+;---------------------------------------;

+; _GetTemplateAddressMap                  ;

+;----------------------------------------------------------------------------;

+; 

+; Protocol prototype

+;   GetTemplateAddressMap (

+;     INTERRUPT_HANDLER_TEMPLATE_MAP *AddressMap

+;   );

+;           

+; Routine Description:

+; 

+;  Return address map of interrupt handler template so that C code can generate

+;  interrupt handlers, and dynamically do address fix.

+; 

+; Arguments:

+; 

+; 

+; Returns: 

+; 

+;   Nothing

+;

+; 

+; Input:  [ebp][0]  = Original ebp

+;         [ebp][4]  = Return address

+;          

+; Output: Nothing

+;           

+; Destroys: Nothing

+;-----------------------------------------------------------------------------;

+_GetTemplateAddressMap  proc near public

+  push    ebp                 ; C prolog

+  mov     ebp, esp

+  pushad

+

+  mov ebx, dword ptr [ebp+08h]

+  mov dword ptr [ebx],    TemplateStart

+  mov dword ptr [ebx+4h], TemplateEnd - TemplateStart

+  

+  ; if code in Template is updated, the value fills into the 3rd parameter 

+  ; also needs update

+  mov dword ptr [ebx+8h], VectorNumber - TemplateStart

+

+  popad

+  pop     ebp

+  ret

+_GetTemplateAddressMap  endp

+

+

+

+;---------------------------------------;

+; _InitializeSelectors                  ;

+;----------------------------------------------------------------------------;

+; 

+; Protocol prototype

+;   InitializeSelectors (

+;   )

+;           

+; Routine Description:

+; 

+;  Creates an new GDT in RAM.  The problem is that our former selectors

+;  were ROM based and the EFI OS Loader does not manipulate the machine state 

+;  to change them (as it would for a 16-bit PC/AT startup code that had to

+;  go from Real Mode to flat mode).

+; 

+; Arguments:

+; 

+; 

+; Returns: 

+; 

+;   Nothing

+;

+; 

+; Input:  [ebp][0]  = Original ebp

+;         [ebp][4]  = Return address

+;          

+; Output: Nothing

+;           

+; Destroys: Nothing

+;-----------------------------------------------------------------------------;

+

+CODE_SELECTOR EQU 10h

+DATA_SELECTOR EQU 18h

+

+_InitializeGdt  proc near public

+  push    ebp                 ; C prolog

+  mov     ebp, esp

+  pushad

+  mov     edi, OFFSET Gdtr    ; Load GDT register

+

+  mov     ax,cs               ; Get the selector data from our code image          

+  mov     es,ax

+  lgdt    FWORD PTR es:[edi]  ; and update the GDTR

+

+  db      067h

+  db      0eah              ; Far Jump Offset:Selector to reload CS

+  dd      OFFSET SelectorRld;   Offset is ensuing instruction boundary

+  dw      CODE_SELECTOR     ;   Selector is our code selector, 10h

+SelectorRld::

+  mov     ax, DATA_SELECTOR ; Update the Base for the new selectors, too

+  mov     ds, ax

+  mov     es, ax

+  mov     fs, ax

+  mov     gs, ax

+  mov     ss, ax  

+

+  popad

+  pop     ebp

+  ret

+_InitializeGdt  endp

+  

+;-----------------------------------------------------------------------------;

+; data

+;-----------------------------------------------------------------------------;

+

+;.data

+        align 16

+

+gdtr    dw GDT_END - GDT_BASE - 1   ; GDT limit

+        dd OFFSET GDT_BASE          ; (GDT base gets set above)

+

+;-----------------------------------------------------------------------------;

+;   global descriptor table (GDT)

+;-----------------------------------------------------------------------------;

+

+        align 16

+

+public GDT_BASE

+GDT_BASE:

+; null descriptor

+NULL_SEL            equ $-GDT_BASE    ; Selector [0]

+        dw 0            ; limit 15:0

+        dw 0            ; base 15:0

+        db 0            ; base 23:16

+        db 0            ; type

+        db 0            ; limit 19:16, flags

+        db 0            ; base 31:24

+

+; linear data segment descriptor

+LINEAR_SEL      equ $-GDT_BASE        ; Selector [0x8]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; linear code segment descriptor

+LINEAR_CODE_SEL equ $-GDT_BASE        ; Selector [0x10]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system data segment descriptor

+SYS_DATA_SEL    equ $-GDT_BASE        ; Selector [0x18]

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 092h         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; system code segment descriptor

+SYS_CODE_SEL    equ $-GDT_BASE

+        dw 0FFFFh       ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 09Ah         ; present, ring 0, data, expand-up, writable

+        db 0CFh                 ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE3_SEL  equ $-GDT_BASE

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE4_SEL  equ $-GDT_BASE

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+; spare segment descriptor

+SPARE5_SEL  equ $-GDT_BASE

+        dw 0            ; limit 0xFFFFF

+        dw 0            ; base 0

+        db 0

+        db 0            ; present, ring 0, data, expand-up, writable

+        db 0            ; page-granular, 32-bit

+        db 0

+

+GDT_END:

+

+

+  end

+

diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/Exception.c b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/Exception.c
new file mode 100644
index 0000000..1c1f12d
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/IA32/Exception.c
@@ -0,0 +1,329 @@
+/** @file

+

+Copyright (c) 2013 Intel Corporation.

+

+Redistribution and use in source and binary forms, with or without

+modification, are permitted provided that the following conditions

+are met:

+

+* Redistributions of source code must retain the above copyright

+notice, this list of conditions and the following disclaimer.

+* Redistributions in binary form must reproduce the above copyright

+notice, this list of conditions and the following disclaimer in

+the documentation and/or other materials provided with the

+distribution.

+* Neither the name of Intel Corporation nor the names of its

+contributors may be used to endorse or promote products derived

+from this software without specific prior written permission.

+

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+Module Name:

+

+  Exception.c

+    

+Abstract:

+

+  IA-32 Exception Handler.

+

+**/

+

+#include "Cpu.h"

+#include "Exception.h"

+

+//

+// Error code flag indicating whether or not an error code will be 

+// pushed on the stack if an exception occurs.

+//

+// 1 means an error code will be pushed, otherwise 0

+//

+// bit 0 - exception 0

+// bit 1 - exception 1

+// etc.

+//

+UINT32 mErrorCodeFlag = 0x00027d00;

+

+//

+// Local Table

+//

+EFI_EXCEPTION_HANDLER mExceptionTable[] = {

+  {

+    EFI_SW_EC_IA32_DIVIDE_ERROR,

+    INTERRUPT_HANDLER_DIVIDE_ZERO

+  },

+  {

+    EFI_SW_EC_IA32_DEBUG,

+    INTERRUPT_HANDLER_DEBUG

+  },

+  {

+    EFI_SW_EC_IA32_NMI,

+    INTERRUPT_HANDLER_NMI

+  },

+  {

+    EFI_SW_EC_IA32_BREAKPOINT,

+    INTERRUPT_HANDLER_BREAKPOINT

+  },

+  {

+    EFI_SW_EC_IA32_OVERFLOW,

+    INTERRUPT_HANDLER_OVERFLOW

+  },

+  {

+    EFI_SW_EC_IA32_BOUND,

+    INTERRUPT_HANDLER_BOUND

+  },

+  {

+    EFI_SW_EC_IA32_INVALID_OPCODE,

+    INTERRUPT_HANDLER_INVALID_OPCODE

+  },

+  //

+  // Interrupt 7, 9, 15 not defined in the debug support protocol. Hence no status codes for them!

+  //

+  {

+    EFI_SW_EC_IA32_INVALID_TSS,

+    INTERRUPT_HANDLER_INVALID_TSS

+  },

+  {

+    EFI_SW_EC_IA32_SEG_NOT_PRESENT,

+    INTERRUPT_HANDLER_SEGMENT_NOT_PRESENT

+  },

+  {

+    EFI_SW_EC_IA32_STACK_FAULT,

+    INTERRUPT_HANDLER_STACK_SEGMENT_FAULT

+  },

+  {

+    EFI_SW_EC_IA32_GP_FAULT,

+    INTERRUPT_HANDLER_GP_FAULT

+  },

+  {

+    EFI_SW_EC_IA32_PAGE_FAULT,

+    INTERRUPT_HANDLER_PAGE_FAULT

+  },

+  {

+    EFI_SW_EC_IA32_FP_ERROR,

+    INTERRUPT_HANDLER_MATH_FAULT

+  },

+  {

+    EFI_SW_EC_IA32_ALIGNMENT_CHECK,

+    INTERRUPT_HANDLER_ALIGNMENT_FAULT

+  },

+  {

+    EFI_SW_EC_IA32_MACHINE_CHECK,

+    INTERRUPT_HANDLER_MACHINE_CHECK

+  },

+  {

+    EFI_SW_EC_IA32_SIMD,

+    INTERRUPT_HANDLER_STREAMING_SIMD

+  }

+};

+

+UINTN mExceptionNumber = sizeof (mExceptionTable) / sizeof (EFI_EXCEPTION_HANDLER);

+

+CPU_STATUS_CODE_TEMPLATE  mStatusCodeData  =  {

+  {

+    sizeof (EFI_STATUS_CODE_DATA),

+    sizeof (EFI_SYSTEM_CONTEXT_IA32),

+    { 0 }

+  },

+  {

+    {0}

+  }

+};

+

+/**

+  Reports StatusCode for Exception

+

+  This function reports status code for exception.

+

+  @param  InterruptType   Interrupt type

+  @param  SystemContext   EFI_SYSTEM_CONTEXT

+

+**/

+VOID

+ReportData (

+  IN EFI_EXCEPTION_TYPE   InterruptType, 

+  IN EFI_SYSTEM_CONTEXT   SystemContext

+  )

+{

+  UINT32                ErrorMessage;

+  UINT32                Index;

+

+  CopyMem (

+    &mStatusCodeData.SystemContext.SystemContextIa32,

+    SystemContext.SystemContextIa32,

+    sizeof (EFI_SYSTEM_CONTEXT_IA32)

+    );

+

+  ErrorMessage = EFI_SOFTWARE_DXE_BS_DRIVER;

+  for (Index = 0; Index < mExceptionNumber; Index++) {

+    if (mExceptionTable[Index].Interrupt == InterruptType) {

+      ErrorMessage |= mExceptionTable[Index].ErrorMessage;

+      break;

+    }

+  }

+

+  REPORT_STATUS_CODE_EX (

+    (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),

+    EFI_SOFTWARE_UNSPECIFIED | ErrorMessage,

+    0,

+    NULL,

+    NULL,

+    (UINT8 *)&mStatusCodeData + sizeof (EFI_STATUS_CODE_DATA),

+    sizeof (EFI_SYSTEM_CONTEXT_IA32)

+    ); 

+}

+

+/**

+  Common exception handler.

+

+  @param InterruptType  Exception type.

+  @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.

+**/

+VOID

+EFIAPI

+CommonExceptionHandler (

+  IN EFI_EXCEPTION_TYPE   InterruptType,

+  IN EFI_SYSTEM_CONTEXT   SystemContext

+  )

+{

+  DEBUG ((

+    EFI_D_ERROR,

+    "!!!! IA32 Exception Type - %08x !!!!\n",

+    InterruptType

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "EIP - %08x, CS - %08x, EFLAGS - %08x\n",

+    SystemContext.SystemContextIa32->Eip,

+    SystemContext.SystemContextIa32->Cs,

+    SystemContext.SystemContextIa32->Eflags

+    ));

+  if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {

+    DEBUG ((

+      EFI_D_ERROR,

+      "ExceptionData - %08x\n",

+      SystemContext.SystemContextIa32->ExceptionData

+      ));

+  }

+  DEBUG ((

+    EFI_D_ERROR,

+    "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",

+    SystemContext.SystemContextIa32->Eax,

+    SystemContext.SystemContextIa32->Ecx,

+    SystemContext.SystemContextIa32->Edx,

+    SystemContext.SystemContextIa32->Ebx

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",

+    SystemContext.SystemContextIa32->Esp,

+    SystemContext.SystemContextIa32->Ebp,

+    SystemContext.SystemContextIa32->Esi,

+    SystemContext.SystemContextIa32->Edi

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",

+    SystemContext.SystemContextIa32->Ds,

+    SystemContext.SystemContextIa32->Es,

+    SystemContext.SystemContextIa32->Fs,

+    SystemContext.SystemContextIa32->Gs,

+    SystemContext.SystemContextIa32->Ss

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "GDTR - %08x %08x, IDTR - %08x %08x\n",

+    SystemContext.SystemContextIa32->Gdtr[0],

+    SystemContext.SystemContextIa32->Gdtr[1],

+    SystemContext.SystemContextIa32->Idtr[0],

+    SystemContext.SystemContextIa32->Idtr[1]

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "LDTR - %08x, TR - %08x\n",

+    SystemContext.SystemContextIa32->Ldtr,

+    SystemContext.SystemContextIa32->Tr

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",

+    SystemContext.SystemContextIa32->Cr0,

+    SystemContext.SystemContextIa32->Cr2,

+    SystemContext.SystemContextIa32->Cr3,

+    SystemContext.SystemContextIa32->Cr4

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",

+    SystemContext.SystemContextIa32->Dr0,

+    SystemContext.SystemContextIa32->Dr1,

+    SystemContext.SystemContextIa32->Dr2,

+    SystemContext.SystemContextIa32->Dr3

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "DR6 - %08x, DR7 - %08x\n",

+    SystemContext.SystemContextIa32->Dr6,

+    SystemContext.SystemContextIa32->Dr7

+    ));

+  

+  //

+  // Report Status Code

+  //

+  ReportData (InterruptType, SystemContext);

+  

+  //

+  // Enter a dead loop.

+  //

+  CpuDeadLoop ();

+

+  return ;

+}

+

+/**

+  Installs the Exception Handler.

+

+  This function installs the Exception Handler.

+

+  @param  ExceptionBegin   The begin number of exception

+

+**/

+VOID

+InitializeException (

+  IN UINT32              ExceptionBegin         

+  )

+{

+  EFI_STATUS                      Status;

+  UINT32                          Index;

+  BOOLEAN                         OldInterruptState;

+

+  //

+  // Disable interrupt

+  //

+  OldInterruptState = SaveAndDisableInterrupts ();

+

+  for (Index = ExceptionBegin; Index < mExceptionNumber; Index++) {

+    //

+    // Register sample excception handler

+    //

+    Status = mCpuArchProtocol.RegisterInterruptHandler (

+                                 &mCpuArchProtocol, 

+                                 mExceptionTable[Index].Interrupt,

+                                 CommonExceptionHandler

+                                 );

+    ASSERT_EFI_ERROR (Status);

+  }

+  //

+  // Restore interrupt state.

+  //

+  SetInterruptState (OldInterruptState);

+}

diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.c b/IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.c
new file mode 100644
index 0000000..cb1ebb1
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.c
@@ -0,0 +1,463 @@
+/** @file

+

+  Code for memory attribute setting

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  MemoryAttribute.c

+

+**/

+

+#include "Cpu.h"

+

+FIXED_MTRR    mFixedMtrrTable[] = {

+  {

+    MTRR_LIB_IA32_MTRR_FIX64K_00000,

+    0,

+    0x10000

+  },

+  {

+    MTRR_LIB_IA32_MTRR_FIX16K_80000,

+    0x80000,

+    0x4000

+  },

+  {

+    MTRR_LIB_IA32_MTRR_FIX16K_A0000,

+    0xA0000,

+    0x4000

+  },

+  {

+    MTRR_LIB_IA32_MTRR_FIX4K_C0000,

+    0xC0000,

+    0x1000

+  },

+  {

+    MTRR_LIB_IA32_MTRR_FIX4K_C8000,

+    0xC8000,

+    0x1000

+  },

+  {

+    MTRR_LIB_IA32_MTRR_FIX4K_D0000,

+    0xD0000,

+    0x1000

+  },

+  {

+    MTRR_LIB_IA32_MTRR_FIX4K_D8000,

+    0xD8000,

+    0x1000

+  },

+  {

+    MTRR_LIB_IA32_MTRR_FIX4K_E0000,

+    0xE0000,

+    0x1000

+  },

+  {

+    MTRR_LIB_IA32_MTRR_FIX4K_E8000,

+    0xE8000,

+    0x1000

+  },

+  {

+    MTRR_LIB_IA32_MTRR_FIX4K_F0000,

+    0xF0000,

+    0x1000

+  },

+  {

+    MTRR_LIB_IA32_MTRR_FIX4K_F8000,

+    0xF8000,

+    0x1000

+  },

+};

+

+/**

+  Gets GCD Mem Space type from MTRR Type.

+

+  This function gets GCD Mem Space type from MTRR Type

+

+  @param  MtrrAttributes  MTRR memory type

+

+  @return GCD Mem Space type

+

+**/

+UINT64

+GetMemorySpaceAttributeFromMtrrType (

+  IN UINT8                MtrrAttributes

+  )

+{

+  switch (MtrrAttributes) {

+  case MTRR_CACHE_UNCACHEABLE:

+    return EFI_MEMORY_UC;

+  case MTRR_CACHE_WRITE_COMBINING:

+    return EFI_MEMORY_WC;

+  case MTRR_CACHE_WRITE_THROUGH:

+    return EFI_MEMORY_WT;

+  case MTRR_CACHE_WRITE_PROTECTED:

+    return EFI_MEMORY_WP;

+  case MTRR_CACHE_WRITE_BACK:

+    return EFI_MEMORY_WB;

+  default:

+    return 0;

+  }

+}

+

+/**

+  Initializes the valid bits mask and valid address mask for MTRRs.

+

+  This function initializes the valid bits mask and valid address mask for MTRRs.

+

+**/

+VOID

+InitializeMtrrMask (

+  VOID

+  )

+{

+  UINT32                              RegEax;

+  UINT8                               PhysicalAddressBits;

+

+  AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);

+

+  if (RegEax >= 0x80000008) {

+    AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);

+  

+    PhysicalAddressBits = (UINT8) RegEax;

+

+    mValidMtrrBitsMask    = LShiftU64 (1, PhysicalAddressBits) - 1;

+    mValidMtrrAddressMask = mValidMtrrBitsMask & 0xfffffffffffff000ULL;

+  } else {

+    mValidMtrrBitsMask    = MTRR_LIB_MSR_VALID_MASK;

+    mValidMtrrAddressMask = MTRR_LIB_CACHE_VALID_ADDRESS;

+  }

+}

+

+/**

+  Searches memory descriptors covered by given memory range.

+

+  This function searches into the Gcd Memory Space for descriptors (from StartIndex

+  to EndIndex) that contains the memory range specified by BaseAddress

+  and Length.

+

+  @param  MemorySpaceMap       Gcd Memory Space Map as array.

+  @param  NumberOfDescriptors  Number of descriptors in map.

+  @param  BaseAddress          BaseAddress for the requested range.

+  @param  Length               Length for the requested range.

+  @param  StartIndex           Start index into the Gcd Memory Space Map.

+  @param  EndIndex             End index into the Gcd Memory Space Map.

+

+  @retval EFI_SUCCESS          Search successfully.

+  @retval EFI_NOT_FOUND        The requested descriptors does not exist.

+

+**/

+EFI_STATUS

+SearchGcdMemorySpaces (

+  IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR     *MemorySpaceMap,

+  IN UINTN                               NumberOfDescriptors,

+  IN EFI_PHYSICAL_ADDRESS                BaseAddress,

+  IN UINT64                              Length,

+  OUT UINTN                              *StartIndex,

+  OUT UINTN                              *EndIndex

+  )

+{

+  UINTN           Index;

+

+  *StartIndex = 0;

+  *EndIndex   = 0;

+  for (Index = 0; Index < NumberOfDescriptors; Index++) {

+    if (BaseAddress >= MemorySpaceMap[Index].BaseAddress &&

+        BaseAddress < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {

+      *StartIndex = Index;

+    }

+    if (BaseAddress + Length - 1 >= MemorySpaceMap[Index].BaseAddress &&

+        BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {

+      *EndIndex = Index;

+      return EFI_SUCCESS;

+    }

+  }

+  return EFI_NOT_FOUND;

+}

+

+/**

+  Sets the attributes for a specified range in Gcd Memory Space Map.

+

+  This function sets the attributes for a specified range in Gcd Memory Space Map.

+

+  @param  MemorySpaceMap       Gcd Memory Space Map as array

+  @param  NumberOfDescriptors  Number of descriptors in map

+  @param  BaseAddress          BaseAddress for the range

+  @param  Length               Length for the range

+  @param  Attributes           Attributes to set

+

+  @retval EFI_SUCCESS          Memory attributes set successfully

+  @retval EFI_NOT_FOUND        The specified range does not exist in Gcd Memory Space

+

+**/

+EFI_STATUS

+SetGcdMemorySpaceAttributes (

+  IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR     *MemorySpaceMap,

+  IN UINTN                               NumberOfDescriptors,

+  IN EFI_PHYSICAL_ADDRESS                BaseAddress,

+  IN UINT64                              Length,

+  IN UINT64                              Attributes

+  )

+{

+  EFI_STATUS            Status;

+  UINTN                 Index;

+  UINTN                 StartIndex;

+  UINTN                 EndIndex;

+  EFI_PHYSICAL_ADDRESS  RegionStart;

+  UINT64                RegionLength;

+

+  //

+  // Get all memory descriptors covered by the memory range

+  //

+  Status = SearchGcdMemorySpaces (

+             MemorySpaceMap,

+             NumberOfDescriptors,

+             BaseAddress,

+             Length,

+             &StartIndex,

+             &EndIndex

+             );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  //

+  // Go through all related descriptors and set attributes accordingly

+  //

+  for (Index = StartIndex; Index <= EndIndex; Index++) {

+    if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {

+      continue;

+    }

+    //

+    // Calculate the start and end address of the overlapping range

+    //

+    if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {

+      RegionStart = BaseAddress;

+    } else {

+      RegionStart = MemorySpaceMap[Index].BaseAddress;

+    }

+    if (BaseAddress + Length - 1 < MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length) {

+      RegionLength = BaseAddress + Length - RegionStart;

+    } else {

+      RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;

+    }

+    //

+    // Set memory attributes according to MTRR attribute and the original attribute of descriptor

+    //

+    gDS->SetMemorySpaceAttributes (

+           RegionStart,

+           RegionLength,

+           (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)

+           );

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Refreshes the GCD Memory Space attributes according to MTRRs.

+  

+  This function refreshes the GCD Memory Space attributes according to MTRRs.

+

+**/

+VOID

+RefreshGcdMemoryAttributes (

+  VOID

+  )

+{

+  EFI_STATUS                          Status;

+  UINTN                               Index;

+  UINTN                               SubIndex;

+  UINT64                              RegValue;

+  EFI_PHYSICAL_ADDRESS                BaseAddress;

+  UINT64                              Length;

+  UINT64                              Attributes;

+  UINT64                              CurrentAttributes;

+  UINT8                               MtrrType;

+  UINTN                               NumberOfDescriptors;

+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR     *MemorySpaceMap;

+  UINT64                              DefaultAttributes;

+  VARIABLE_MTRR                       VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];

+  MTRR_FIXED_SETTINGS                 MtrrFixedSettings;

+  UINTN                               FirmwareVariableMtrrCount;

+  UINT8                               DefaultMemoryType;

+

+  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();

+

+  mIsFlushingGCD = TRUE;

+  MemorySpaceMap = NULL;

+

+  //

+  // Initialize the valid bits mask and valid address mask for MTRRs

+  //

+  InitializeMtrrMask ();

+

+  //

+  // Get the memory attribute of variable MTRRs

+  //

+  MtrrGetMemoryAttributeInVariableMtrr (

+    mValidMtrrBitsMask,

+    mValidMtrrAddressMask,

+    VariableMtrr

+    );

+

+  //

+  // Get the memory space map from GCD

+  //

+  Status = gDS->GetMemorySpaceMap (

+                  &NumberOfDescriptors,

+                  &MemorySpaceMap

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  DefaultMemoryType = (UINT8) MtrrGetDefaultMemoryType ();

+  DefaultAttributes = GetMemorySpaceAttributeFromMtrrType (DefaultMemoryType);

+

+  //

+  // Set default attributes to all spaces.

+  //

+  for (Index = 0; Index < NumberOfDescriptors; Index++) {

+    if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {

+      continue;

+    }

+    gDS->SetMemorySpaceAttributes (

+           MemorySpaceMap[Index].BaseAddress,

+           MemorySpaceMap[Index].Length,

+           (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) |

+           (MemorySpaceMap[Index].Capabilities & DefaultAttributes)

+           );

+  }

+  

+  //

+  // Go for variable MTRRs with WB attribute

+  //

+  for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {

+    if (VariableMtrr[Index].Valid &&

+        VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) {

+      SetGcdMemorySpaceAttributes (

+        MemorySpaceMap,

+        NumberOfDescriptors,

+        VariableMtrr[Index].BaseAddress,

+        VariableMtrr[Index].Length,

+        EFI_MEMORY_WB

+        );

+    }

+  }

+  //

+  // Go for variable MTRRs with the attribute except for WB and UC attributes

+  //

+  for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {

+    if (VariableMtrr[Index].Valid &&

+        VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK &&

+        VariableMtrr[Index].Type != MTRR_CACHE_UNCACHEABLE) {

+      Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8) VariableMtrr[Index].Type);

+      SetGcdMemorySpaceAttributes (

+        MemorySpaceMap,

+        NumberOfDescriptors,

+        VariableMtrr[Index].BaseAddress,

+        VariableMtrr[Index].Length,

+        Attributes

+        );

+    }

+  }

+  //

+  // Go for variable MTRRs with UC attribute

+  //

+  for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {

+    if (VariableMtrr[Index].Valid &&

+        VariableMtrr[Index].Type == MTRR_CACHE_UNCACHEABLE) {

+      SetGcdMemorySpaceAttributes (

+        MemorySpaceMap,

+        NumberOfDescriptors,

+        VariableMtrr[Index].BaseAddress,

+        VariableMtrr[Index].Length,

+        EFI_MEMORY_UC

+        );

+    }

+  }

+

+  //

+  // Go for fixed MTRRs

+  //

+  Attributes  = 0;

+  BaseAddress = 0;

+  Length      = 0;

+  MtrrGetFixedMtrr (&MtrrFixedSettings);

+  for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {

+    RegValue = MtrrFixedSettings.Mtrr[Index];

+    //

+    // Check for continuous fixed MTRR sections

+    //

+    for (SubIndex = 0; SubIndex < 8; SubIndex++) {

+      MtrrType = (UINT8) RShiftU64 (RegValue, SubIndex * 8);

+      CurrentAttributes = GetMemorySpaceAttributeFromMtrrType (MtrrType);

+      if (Length == 0) {

+        //

+        // A new MTRR attribute begins

+        //

+        Attributes = CurrentAttributes;

+      } else {

+        //

+        // If fixed MTRR attribute changed, then set memory attribute for previous atrribute

+        //

+        if (CurrentAttributes != Attributes) {

+          SetGcdMemorySpaceAttributes (

+            MemorySpaceMap,

+            NumberOfDescriptors,

+            BaseAddress,

+            Length,

+            Attributes

+            );

+          BaseAddress = mFixedMtrrTable[Index].BaseAddress + mFixedMtrrTable[Index].Length * SubIndex;

+          Length = 0;

+          Attributes = CurrentAttributes;

+        }

+      }

+      Length += mFixedMtrrTable[Index].Length;

+    }

+  }

+  //

+  // Handle the last fixed MTRR region

+  //

+  SetGcdMemorySpaceAttributes (

+    MemorySpaceMap,

+    NumberOfDescriptors,

+    BaseAddress,

+    Length,

+    Attributes

+    );

+

+  //

+  // Free memory space map allocated by GCD service GetMemorySpaceMap ()

+  //

+  if (MemorySpaceMap != NULL) {

+    FreePool (MemorySpaceMap);

+  }

+

+  mIsFlushingGCD = FALSE;

+}

diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.h b/IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.h
new file mode 100644
index 0000000..7b338c1
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/MemoryAttribute.h
@@ -0,0 +1,50 @@
+/** @file

+

+  Include file for memory attribute setting

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  MemoryAttribute.h

+

+**/

+

+#ifndef _EFI_MEMORY_ATTRIB_H_

+#define _EFI_MEMORY_ATTRIB_H_

+

+#define EFI_MEMORY_CACHETYPE_MASK     (EFI_MEMORY_UC  | \

+                                       EFI_MEMORY_WC  | \

+                                       EFI_MEMORY_WT  | \

+                                       EFI_MEMORY_WB  | \

+                                       EFI_MEMORY_UCE   \

+                                       )

+

+extern BOOLEAN    mIsFlushingGCD;

+

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.c b/IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.c
new file mode 100644
index 0000000..7e9678e
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.c
@@ -0,0 +1,113 @@
+/** @file

+

+  Code for MTRR synchronzation.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  MtrrSync.c

+

+**/

+

+#include "Cpu.h"

+

+MTRR_SETTINGS   *mMtrrTable;

+

+/**

+  Initialize memory region for MTRR data.

+  

+  This function allocates ACPI NVS memory for MTRR data.

+  Each time MTRRs are written, this memory region will be updated accordingly.

+

+**/

+VOID

+InitializeMtrrData (

+  VOID

+  )

+{

+  //

+  // Allocate memory for fixed MTRRs, variable MTRRs and MTRR_DEF_TYPE

+  //

+  mMtrrTable = AllocateAcpiNvsMemoryBelow4G (sizeof (MTRR_SETTINGS));

+

+  PcdSet64 (PcdCpuMtrrTableAddress, (UINT64) (UINTN) mMtrrTable);

+}

+

+/**

+  Synchronzies up the MTRR values with BSP for calling processor.

+

+  This function synchronzies up the MTRR values with BSP for calling processor.

+

+  @param  Buffer         Mtrr table address.

+

+**/

+VOID

+EFIAPI

+LoadMtrrData (

+  VOID    *Buffer

+  )

+{

+  MtrrSetAllMtrrs (mMtrrTable);

+}

+

+/**

+  Allocate EfiACPIMemoryNVS below 4G memory address.

+

+  This function allocates EfiACPIMemoryNVS below 4G memory address.

+

+  @param  Size         Size of memory to allocate.

+  

+  @return Allocated address for output.

+

+**/

+VOID*

+AllocateAcpiNvsMemoryBelow4G (

+  IN   UINTN   Size

+  )

+{

+  UINTN                 Pages;

+  EFI_PHYSICAL_ADDRESS  Address;

+  EFI_STATUS            Status;

+  VOID*                 Buffer;

+

+  Pages = EFI_SIZE_TO_PAGES (Size);

+  Address = 0xffffffff;

+

+  Status  = gBS->AllocatePages (

+                   AllocateMaxAddress,

+                   EfiACPIMemoryNVS,

+                   Pages,

+                   &Address

+                   );

+  ASSERT_EFI_ERROR (Status);

+

+  Buffer = (VOID *) (UINTN) Address;

+  ZeroMem (Buffer, Size);

+

+  return Buffer;

+}

diff --git a/IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.h b/IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.h
new file mode 100644
index 0000000..e6fb549
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuArchDxe/MtrrSync.h
@@ -0,0 +1,85 @@
+/** @file

+

+  Include file for MTRR synchronzation.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  MtrrSync.h

+

+**/

+

+#ifndef _EFI_MTRR_SYNC_H_

+#define _EFI_MTRR_SYNC_H_

+

+#include "Cpu.h"

+

+extern MTRR_SETTINGS   *mMtrrTable;

+

+/**

+  Initialize memory region for MTRR data.

+  

+  This function allocates ACPI NVS memory for MTRR data, and fills the region

+  with current MTRR data. Each time MTRRs are written, this memory region

+  will be updated accordingly.

+

+**/

+VOID

+InitializeMtrrData (

+  VOID

+  );

+

+/**

+  Synchronzies up the MTRR values with BSP for calling processor.

+

+  This function synchronzies up the MTRR values with BSP for calling processor.

+

+  @param  Buffer         Mtrr table address.

+

+**/

+VOID

+EFIAPI

+LoadMtrrData (

+  VOID    *Buffer

+  );

+

+/**

+  Allocate EfiACPIMemoryNVS below 4G memory address.

+

+  This function allocates EfiACPIMemoryNVS below 4G memory address.

+

+  @param  Size         Size of memory to allocate.

+  

+  @return Allocated address for output.

+

+**/

+VOID*

+AllocateAcpiNvsMemoryBelow4G (

+  IN   UINTN   Size

+  );

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Analysis.c b/IA32FamilyCpuBasePkg/CpuMpDxe/Analysis.c
new file mode 100644
index 0000000..8921e60
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Analysis.c
@@ -0,0 +1,197 @@
+/** @file

+  Code for Analysis phase.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  Analysis.c

+

+**/

+

+#include "Cpu.h"

+#include "Feature.h"

+

+/**

+  Configures Processor Feature List for all processors.

+

+  This function configures Processor Feature List for all processors.

+

+**/

+VOID

+ConfigProcessorFeatureList (

+  VOID

+  )

+{

+  //

+  // Configure Feature List for Max CPUID Value Limit

+  //

+  if (FeaturePcdGet (PcdCpuMaxCpuIDValueLimitFlag)) {

+    MaxCpuidLimitConfigFeatureList ();

+  }

+  //

+  // Configure Feature List for execute disable bit

+  //

+  if (FeaturePcdGet (PcdCpuExecuteDisableBitFlag)) {

+    XdConfigFeatureList ();

+  }

+}

+

+/**

+  Produces Register Tables for all processors.

+

+  This function produces Register Tables for all processors.

+

+**/

+VOID

+ProduceRegisterTable (

+  VOID

+  )

+{

+

+  UINTN          ProcessorNumber;

+  UINT8          Index;

+  CPU_FEATURE_ID FeatureID;

+  VOID           *Attribute;

+

+  //

+  // Parse Processor Feature Lists and translate to Register Tables for all processors.

+  //

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+    

+    //

+    // Traverse Processor Feature List for this logical processor.

+    //

+    Index = 1;

+    FeatureID = GetProcessorFeatureEntry (ProcessorNumber, Index, &Attribute);

+    Index++;

+    while (FeatureID != CpuFeatureMaximum) {

+

+      switch (FeatureID) {

+

+      case MaxCpuidValueLimit:

+        if (FeaturePcdGet (PcdCpuMaxCpuIDValueLimitFlag)) {

+          MaxCpuidLimitReg (ProcessorNumber, Attribute);

+        }

+        break;

+

+      case ExecuteDisableBit:

+        if (FeaturePcdGet (PcdCpuExecuteDisableBitFlag)) {

+          XdReg (ProcessorNumber, Attribute);

+        }

+        break;

+

+      default:

+        break;

+      }

+

+      FeatureID = GetProcessorFeatureEntry (ProcessorNumber, Index, &Attribute);

+      Index++;

+    }

+  }

+}

+

+/**

+  Produces Pre-SMM-Init Register Tables for all processors.

+

+  This function produces Pre-SMM-Init Register Tables for all processors.

+

+**/

+VOID

+ProducePreSmmInitRegisterTable (

+  VOID

+  )

+{

+  UINTN  ProcessorNumber;

+  UINT32 ApicId;

+

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+    ApicId = mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber].CpuMiscData.InitialApicID;

+    mCpuConfigConextBuffer.PreSmmInitRegisterTable[ProcessorNumber].InitialApicId = ApicId;

+  }

+}

+

+/**

+  Produces register table according to output of Data Collection phase.

+  

+  This function produces register table according to output of Data Collection phase.

+

+**/

+VOID

+AnalysisPhase (

+  VOID

+  )

+{

+  UINTN                     Index;

+  UINTN                     ProcessorNumber;

+  CPU_REGISTER_TABLE        *RegisterTable;

+  CPU_REGISTER_TABLE_ENTRY  *RegisterTableEntry;

+  UINT8                     CallbackSignalValue;

+

+  //

+  // Set PcdCpuCallbackSignal to trigger callback function, and reads the value back.

+  //

+  CallbackSignalValue = SetAndReadCpuCallbackSignal (CPU_PROCESSOR_FEATURE_LIST_CONFIG_SIGNAL);

+  //

+  // Checks whether the callback function requests to bypass Processor Feature List configuration.

+  //

+  if (CallbackSignalValue != CPU_BYPASS_SIGNAL) {

+    //

+    // Configure Processor Feature List for all logical processors.

+    //

+    ConfigProcessorFeatureList ();

+  }

+

+  //

+  // Set PcdCpuCallbackSignal to trigger callback function, and reads the value back.

+  //

+  CallbackSignalValue = SetAndReadCpuCallbackSignal (CPU_REGISTER_TABLE_TRANSLATION_SIGNAL);

+  //

+  // Checks whether the callback function requests to bypass Register Table translation.

+  //

+  if (CallbackSignalValue != CPU_BYPASS_SIGNAL) {

+    //

+    // Produce register tables for all logical processors.

+    //

+    ProduceRegisterTable ();

+  }

+

+  //

+  // Debug information

+  //

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+

+    RegisterTable = &mCpuConfigConextBuffer.RegisterTable[ProcessorNumber];

+    for (Index = 0; Index < RegisterTable->TableLength; Index++) {

+      RegisterTableEntry = &RegisterTable->RegisterTableEntry[Index];

+      DEBUG ((EFI_D_INFO, "Processor: %d: MSR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n", ProcessorNumber, RegisterTableEntry->Index, RegisterTableEntry->ValidBitStart, RegisterTableEntry->ValidBitLength, RegisterTableEntry->Value));

+    }

+  }

+  DEBUG ((EFI_D_INFO, "Capability: %8x\r\n", PcdGet32 (PcdCpuProcessorFeatureCapability)));

+  DEBUG ((EFI_D_INFO, "Configuration: %8x\r\n", PcdGet32 (PcdCpuProcessorFeatureUserConfiguration)));

+  DEBUG ((EFI_D_INFO, "Setting: %8x\r\n", PcdGet32 (PcdCpuProcessorFeatureSetting)));

+}

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Cpu.h b/IA32FamilyCpuBasePkg/CpuMpDxe/Cpu.h
new file mode 100644
index 0000000..ad36c9d
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Cpu.h
@@ -0,0 +1,298 @@
+/** @file

+

+  Include file for CPU DXE Module

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  Cpu.h

+

+**/

+

+#ifndef _CPU_DXE_H_

+#define _CPU_DXE_H_

+

+#include "MpCommon.h"

+

+#define PLATFORM_DESKTOP           0

+#define PLATFORM_MOBILE            1

+#define PLATFORM_SERVER            2

+

+#define EFI_CPUID_CORE_TOPOLOGY    0x0B

+

+//

+// The definitions below follow the naming rules.

+//   Definitions beginning with "B_" are bits within registers

+//   Definitions beginning with "N_" are the bit position

+//   Definitions with "_CPUID_" are CPUID bit fields

+//   Definitions with "_MSR_" are MSR bit fields

+//   Definitions with "N_*_START" are the bit start position

+//   Definitions with "N_*_STOP" are the bit stop position

+//   Definitions with "B_*_MASK" are the bit mask for the register values

+//

+

+//

+// Bit definitions for CPUID EAX = 1

+//

+// ECX

+#define N_CPUID_MONITOR_MWAIT_SUPPORT               3

+#define N_CPUID_VMX_SUPPORT                         5

+#define N_CPUID_SMX_SUPPORT                         6

+#define N_CPUID_EIST_SUPPORT                        7

+#define N_CPUID_TM2_SUPPORT                         8

+#define N_CPUID_DCA_SUPPORT                         18

+#define N_CPUID_X2APIC_SUPPORT                      21

+#define N_CPUID_AESNI_SUPPORT                       25

+// EDX

+#define N_CPUID_MCE_SUPPORT                         7

+#define N_CPUID_MCA_SUPPORT                         14

+#define N_CPUID_TM_SUPPORT                          29

+#define N_CPUID_PBE_SUPPORT                         31

+

+//

+// Bit definitions for CPUID EAX = 80000001h

+//

+// EDX

+#define N_CPUID_XD_BIT_AVAILABLE                    20

+

+//

+// Bit definitions for MSR_IA32_APIC_BASE (ECX = 1Bh)

+//

+#define N_MSR_BSP_FLAG                              8

+#define B_MSR_ENABLE_X2APIC_MODE                    BIT10

+#define N_MSR_ENABLE_X2APIC_MODE                    10

+#define N_MSR_APIC_GLOBAL_ENABLE                    11

+

+//

+// Bit definitions for MSR_IA32_MISC_ENABLE (ECX = 1A0h)

+//

+#define N_MSR_LIMIT_CPUID_MAXVAL                    22

+#define N_MSR_XD_BIT_DISABLE                        34

+

+extern EFI_PHYSICAL_ADDRESS        mStartupVector;

+

+extern BOOLEAN                     mRestoreSettingAfterInit;

+extern UINT8                       mPlatformType;

+extern ACPI_CPU_DATA               *mAcpiCpuData;

+

+/**

+  Collects basic processor data for calling processor.

+

+  This function collects basic processor data for calling processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+CollectBasicProcessorData (

+  IN UINTN  ProcessorNumber

+  );

+

+/**

+  Early MP Initialization.

+  

+  This function does early MP initialization, including MTRR sync and first time microcode load.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+EarlyMpInit (

+  IN UINTN  ProcessorNumber

+  );

+

+/**

+  Collects data from all logical processors.

+

+  This function collects data from all logical processors

+

+**/

+VOID

+DataCollectionPhase (

+  VOID

+  );

+

+/**

+  Produces register table according to output of Data Collection phase.

+  

+  This function produces register table according to output of Data Collection phase.

+

+**/

+VOID

+AnalysisPhase (

+  VOID

+  );

+

+/**

+  Programs processor registers according to register tables.

+

+  This function programs processor registers according to register tables.

+

+**/

+VOID

+SettingPhase (

+  VOID

+  );

+

+/**

+  Produces Pre-SMM-Init Register Tables for all processors.

+

+  This function produces Pre-SMM-Init Register Tables for all processors.

+

+**/

+VOID

+ProducePreSmmInitRegisterTable (

+  VOID

+  );

+

+/**

+  Wakes up APs for the first time to count their number and collect BIST data.

+

+  This function wakes up APs for the first time to count their number and collect BIST data.

+

+**/

+VOID

+WakeupAPAndCollectBist (

+  VOID

+  );

+

+/**

+  Configures all logical processors with three-phase architecture.

+  

+  This function configures all logical processors with three-phase architecture.

+

+**/

+VOID

+ProcessorConfigurationuration (

+  VOID

+  );

+

+/**

+  Select least-feature processor as BSP.

+  

+  This function selects least-feature processor as BSP.

+

+**/

+VOID

+SelectLfpAsBsp (

+  VOID

+  );

+

+/**

+  Add SMBIOS Processor Type and Cache Type tables for the CPU.

+**/

+VOID

+AddCpuSmbiosTables (

+  VOID

+  );

+

+/**

+  Prepare ACPI NVS memory below 4G memory for use of S3 resume.

+  

+  This function allocates ACPI NVS memory below 4G memory for use of S3 resume,

+  and saves data into the memory region.

+

+  @param  Context   The Context save the info.

+  

+**/

+VOID

+SaveCpuS3Data (

+  VOID    *Context

+  );

+

+/**

+  Programs registers for the calling processor.

+

+  This function programs registers for the calling processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+SetProcessorRegister (

+  IN UINTN  ProcessorNumber

+  );

+

+/**

+  Programs registers before SMM initialization for the calling processor.

+

+  This function programs registers before SMM initialization for the calling processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+SetPreSmmInitProcessorRegister (

+  IN UINTN  ProcessorNumber

+  );

+

+/**

+  Label of start of AP machine check handler.

+

+  This is just a label of start of AP machine check handler.

+

+**/

+VOID

+EFIAPI

+ApMachineCheckHandler (

+  VOID

+  );

+

+/**

+  Label of end of AP machine check handler.

+

+  This is just a label of end of AP machine check handler.

+

+**/

+VOID

+EFIAPI

+ApMachineCheckHandlerEnd (

+  VOID

+  );

+

+/**

+  This function gets Package ID/Core ID/Thread ID of the processor.

+

+  The algorithm below assumes the target system has symmetry across physical package boundaries

+  with respect to the number of logical processors per package, number of cores per package.

+

+  @param  InitialApicId  Initial APIC ID for determing processor topology.

+  @param  Location       Pointer to EFI_CPU_PHYSICAL_LOCATION structure.

+  @param  ThreadIdBits   Number of bits occupied by Thread ID portion.

+  @param  CoreIdBits     Number of bits occupied by Core ID portion.

+

+**/

+VOID

+ExtractProcessorLocation (

+  IN  UINT32                    InitialApicId,

+  OUT EFI_CPU_PHYSICAL_LOCATION *Location,

+  OUT UINTN                     *ThreadIdBits,

+  OUT UINTN                     *CoreIdBits

+  );

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/CpuMpDxe.inf b/IA32FamilyCpuBasePkg/CpuMpDxe/CpuMpDxe.inf
new file mode 100644
index 0000000..934f86c
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/CpuMpDxe.inf
@@ -0,0 +1,179 @@
+## @file

+# Component description file for CPU MP DXE Driver.

+#

+# CPU DXE Driver that configures multi-processor environment, logs data to datahub

+#  for processor subclass and cache subclass, and installs CPU Architecture Protocol and MP

+#  Services Protocol

+# Copyright (c) 2013 Intel Corporation.

+#

+# Redistribution and use in source and binary forms, with or without

+# modification, are permitted provided that the following conditions

+# are met:

+#

+# * Redistributions of source code must retain the above copyright

+# notice, this list of conditions and the following disclaimer.

+# * Redistributions in binary form must reproduce the above copyright

+# notice, this list of conditions and the following disclaimer in

+# the documentation and/or other materials provided with the

+# distribution.

+# * Neither the name of Intel Corporation nor the names of its

+# contributors may be used to endorse or promote products derived

+# from this software without specific prior written permission.

+#

+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+#

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = CpuMpDxe

+  FILE_GUID                      = 40BEAB40-CECE-4909-B133-20A413AE19E9

+  MODULE_TYPE                    = DXE_DRIVER

+  VERSION_STRING                 = 1.0

+  ENTRY_POINT                    = MultiProcessorInitialize

+

+#

+# The following information is for reference only and not required by the build tools.

+#

+#  VALID_ARCHITECTURES           = IA32 X64

+#

+#  Create Event Guid C Name:  Event Type: EVENT_TYPE_PERIODIC_TIMER

+#

+#  HOB Guid C Name: gEfiHtBistHobGuid Hob Type: GUID_EXTENSION

+#

+

+[Sources]

+  SMBIOS/ProcessorSubClass.c

+  SMBIOS/ProcessorData.c

+  SMBIOS/Processor.h

+  SMBIOS/CpuSmbios.c

+  SMBIOS/CacheSubClass.c

+  SMBIOS/Cache.h

+  Xd.h

+  Xd.c

+  Setting.c

+  SelectLfp.c

+  ProcessorConfig.c

+  MpService.h

+  MpService.c

+  MpCommon.h

+  MpCommon.c

+  LimitCpuIdValue.h

+  LimitCpuIdValue.c

+  Feature.h

+  DataCollection.c

+  Cpu.h

+  MpApic.c

+  MpApic.h

+  Analysis.c

+  Strings.uni

+

+[Sources.Ia32]

+  IA32/MpFuncs.asm

+  IA32/MpFuncs.S

+  IA32/CpuOnlyReset.h

+  IA32/CpuOnlyReset.c

+  IA32/CpuAsm.asm

+  IA32/CpuAsm.S

+  IA32/AsmInclude.inc

+  IA32/ArchSpecificDef.h

+  IA32/ArchSpecific.c

+

+[Packages]

+  MdePkg/MdePkg.dec

+  MdeModulePkg/MdeModulePkg.dec

+  IntelFrameworkPkg/IntelFrameworkPkg.dec

+  IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec

+  UefiCpuPkg/UefiCpuPkg.dec

+  IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec

+

+[LibraryClasses]

+  TimerLib

+  DxeServicesTableLib

+  CpuConfigLib

+  CpuLib

+  IoLib

+  PcdLib

+  UefiRuntimeServicesTableLib

+  UefiBootServicesTableLib

+  MemoryAllocationLib

+  UefiDriverEntryPoint

+  ReportStatusCodeLib

+  BaseMemoryLib

+  HiiLib

+  HobLib

+  UefiLib

+  DebugLib

+  BaseLib

+  SynchronizationLib

+  CpuOnlyResetLib

+  UefiCpuLib

+  MtrrLib

+  S3BootScriptLib

+  DebugAgentLib

+  LocalApicLib

+  PrintLib

+

+[Guids]

+  gEfiHtBistHobGuid                             # ALWAYS_CONSUMED

+  gEfiEventExitBootServicesGuid                 # ALWAYS_CONSUMED

+  gIdleLoopEventGuid                            # ALWAYS_CONSUMED

+

+[Protocols]

+  gEfiSmbiosProtocolGuid                        # PROTOCOL ALWAYS_CONSUMED

+  gEfiMpServiceProtocolGuid                     # PROTOCOL ALWAYS_PRODUCED

+  gEfiCpuArchProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED

+  gEfiGenericMemTestProtocolGuid                ## SOMETIMES_CONSUMES

+  gEfiLegacyBiosProtocolGuid                    ## SOMETIMES_CONSUMES

+  gEfiSmmConfigurationProtocolGuid              # PROTOCOL ALWAYS_CONSUMED

+  gEfiTimerArchProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED

+  gEfiTcgProtocolGuid                           ## SOMETIMES_CONSUMES

+

+[FeaturePcd]

+  gEfiCpuTokenSpaceGuid.PcdCpuSelectLfpAsBspFlag

+  gEfiCpuTokenSpaceGuid.PcdCpuExecuteDisableBitFlag

+  gEfiCpuTokenSpaceGuid.PcdCpuMaxCpuIDValueLimitFlag

+

+[FixedPcd]

+  gEfiCpuTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber

+  gEfiCpuTokenSpaceGuid.PcdCpuApLoopMode

+

+[Pcd]

+  gEfiCpuTokenSpaceGuid.PcdPlatformType

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuAssetTags

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketNames

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketCount

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuFrequencyLists

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxFsbFrequency

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxCoreFrequency

+  gEfiCpuTokenSpaceGuid.PcdCpuApStackSize

+  gEfiCpuTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureSetting

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureCapability

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureUserConfiguration

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureSettingEx1

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureCapabilityEx1

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureUserConfigurationEx1

+  gEfiCpuTokenSpaceGuid.PcdCpuConfigContextBuffer

+  gEfiCpuTokenSpaceGuid.PcdCpuCallbackSignal

+  gEfiCpuTokenSpaceGuid.PcdIsPowerOnReset

+  gEfiCpuTokenSpaceGuid.PcdCpuPageTableAddress

+  gEfiCpuTokenSpaceGuid.PcdCpuMtrrTableAddress

+  gEfiCpuTokenSpaceGuid.PcdCpuS3DataAddress

+  gEfiCpuTokenSpaceGuid.PcdCpuSocketId

+  gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdEbdaReservedMemorySize

+

+[Depex]

+  gEfiSmbiosProtocolGuid AND gEfiTimerArchProtocolGuid

+

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/DataCollection.c b/IA32FamilyCpuBasePkg/CpuMpDxe/DataCollection.c
new file mode 100644
index 0000000..61b48e6
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/DataCollection.c
@@ -0,0 +1,765 @@
+/** @file

+  Code for Data Collection phase.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  DataCollection.c

+

+**/

+

+#include "Cpu.h"

+#include "Feature.h"

+

+BOOLEAN    HtCapable  = FALSE;

+BOOLEAN    CmpCapable = FALSE;

+

+/**

+  Collects Local APIC data of the processor.

+

+  This function collects Local APIC base, verion, and APIC ID of the processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor

+

+**/

+VOID

+CollectApicData (

+  UINTN    ProcessorNumber

+  )

+{

+  CPU_MISC_DATA          *CpuMiscData;

+  UINT32                 LocalApicBaseAddress;

+

+  CpuMiscData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber].CpuMiscData;

+

+  LocalApicBaseAddress = (UINT32) GetLocalApicBaseAddress();

+  CpuMiscData->ApicBase    = LocalApicBaseAddress;

+  //

+  // Read bits 0..7 of Local APIC Version Register for Local APIC version.

+  //

+  CpuMiscData->ApicVersion = GetApicVersion () & 0xff;

+  //

+  // Read bits 24..31 of Local APIC ID Register for Local APIC ID

+  //

+  CpuMiscData->ApicID        = GetApicId ();

+  CpuMiscData->InitialApicID = GetInitialApicId ();

+}

+

+/**

+  Collects all CPUID leafs the processor.

+

+  This function collects all CPUID leafs the processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor

+

+**/

+VOID

+CollectCpuidLeafs (

+  UINTN    ProcessorNumber

+  )

+{

+  CPU_COLLECTED_DATA   *CpuCollectedData;

+  EFI_CPUID_REGISTER   *CpuidRegisters;

+  UINT32               Index;

+

+  CpuCollectedData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber];

+  //

+  // Collect basic CPUID information.

+  //

+  CpuidRegisters = CpuCollectedData->CpuidData.CpuIdLeaf;

+  for (Index = 0; Index < GetNumberOfCpuidLeafs (ProcessorNumber, BasicCpuidLeaf); Index++) {

+    AsmCpuid (

+      Index,

+      &CpuidRegisters->RegEax,

+      &CpuidRegisters->RegEbx,

+      &CpuidRegisters->RegEcx,

+      &CpuidRegisters->RegEdx

+      );

+    CpuidRegisters++;

+  }

+

+  //

+  // Collect extended function CPUID information.

+  //

+  for (Index = 0; Index < GetNumberOfCpuidLeafs (ProcessorNumber, ExtendedCpuidLeaf); Index++) {

+    AsmCpuid (

+      Index + 0x80000000,

+      &CpuidRegisters->RegEax,

+      &CpuidRegisters->RegEbx,

+      &CpuidRegisters->RegEcx,

+      &CpuidRegisters->RegEdx

+      );

+    CpuidRegisters++;

+  }

+

+  //

+  // Collect additional Cache & TLB information, if exists.

+  //

+  for (Index = 1; Index < GetNumberOfCpuidLeafs (ProcessorNumber, CacheAndTlbCpuidLeafs); Index++) {

+    AsmCpuid (

+      2,

+      &CpuidRegisters->RegEax,

+      &CpuidRegisters->RegEbx,

+      &CpuidRegisters->RegEcx,

+      &CpuidRegisters->RegEdx

+      );

+    CpuidRegisters++;

+  }

+

+  //

+  // Collect Deterministic Cache Parameters Leaf.

+  //

+  for (Index = 0; Index < GetNumberOfCpuidLeafs (ProcessorNumber, DeterministicCacheParametersCpuidLeafs); Index++) {

+    AsmCpuidEx (

+      4,

+      Index,

+      &CpuidRegisters->RegEax,

+      &CpuidRegisters->RegEbx,

+      &CpuidRegisters->RegEcx,

+      &CpuidRegisters->RegEdx

+      );

+    CpuidRegisters++;

+  }

+

+  //

+  // Collect Extended Topology Enumeration Leaf.

+  //

+  for (Index = 0; Index < GetNumberOfCpuidLeafs (ProcessorNumber, ExtendedTopologyEnumerationCpuidLeafs); Index++) {

+    AsmCpuidEx (

+      EFI_CPUID_CORE_TOPOLOGY,

+      Index,

+      &CpuidRegisters->RegEax,

+      &CpuidRegisters->RegEbx,

+      &CpuidRegisters->RegEcx,

+      &CpuidRegisters->RegEdx

+      );

+    CpuidRegisters++;

+  }

+}

+

+/**

+  Collects physical location of the processor.

+

+  This function gets Package ID/Core ID/Thread ID of the processor.

+

+  The algorithm below assumes the target system has symmetry across physical package boundaries

+  with respect to the number of logical processors per package, number of cores per package.

+

+  @param  InitialApicId  Initial APIC ID for determing processor topology.

+  @param  Location       Pointer to EFI_CPU_PHYSICAL_LOCATION structure.

+  @param  ThreadIdBits   Number of bits occupied by Thread ID portion.

+  @param  CoreIdBits     Number of bits occupied by Core ID portion.

+

+**/

+VOID

+ExtractProcessorLocation (

+  IN  UINT32                    InitialApicId,

+  OUT EFI_CPU_PHYSICAL_LOCATION *Location,

+  OUT UINTN                     *ThreadIdBits,

+  OUT UINTN                     *CoreIdBits

+  )

+{

+  BOOLEAN  TopologyLeafSupported;

+  UINTN    ThreadBits;

+  UINTN    CoreBits;

+  UINT32   RegEax;

+  UINT32   RegEbx;

+  UINT32   RegEcx;

+  UINT32   RegEdx;

+  UINT32   MaxCpuIdIndex;

+  UINT32   SubIndex;

+  UINTN    LevelType;

+  UINT32   MaxLogicProcessorsPerPackage;

+  UINT32   MaxCoresPerPackage;

+

+  //

+  // Check if the processor is capable of supporting more than one logical processor.

+  //

+  AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);

+  if ((RegEdx & BIT28) == 0) {

+    Location->Thread  = 0;

+    Location->Core    = 0;

+    Location->Package = 0;

+    *ThreadIdBits     = 0;

+    *CoreIdBits       = 0;

+    return;

+  }

+

+  ThreadBits = 0;

+  CoreBits = 0;

+  

+  //

+  // Assume three-level mapping of APIC ID: Package:Core:SMT.

+  //

+

+  TopologyLeafSupported = FALSE;

+  //

+  // Get the max index of basic CPUID

+  //

+  AsmCpuid (EFI_CPUID_SIGNATURE, &MaxCpuIdIndex, NULL, NULL, NULL);

+

+  //

+  // If the extended topology enumeration leaf is available, it

+  // is the preferred mechanism for enumerating topology.

+  //

+  if (MaxCpuIdIndex >= EFI_CPUID_EXTENDED_TOPOLOGY) {

+    AsmCpuidEx (EFI_CPUID_EXTENDED_TOPOLOGY, 0, &RegEax, &RegEbx, &RegEcx, NULL);

+    //

+    // If CPUID.(EAX=0BH, ECX=0H):EBX returns zero and maximum input value for

+    // basic CPUID information is greater than 0BH, then CPUID.0BH leaf is not 

+    // supported on that processor.

+    //

+    if (RegEbx != 0) {

+      TopologyLeafSupported = TRUE;

+

+      //

+      // Sub-leaf index 0 (ECX= 0 as input) provides enumeration parameters to extract 

+      // the SMT sub-field of x2APIC ID.

+      //

+      LevelType = (RegEcx >> 8) & 0xff;

+      ASSERT (LevelType == EFI_CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT);

+      ThreadBits = RegEax & 0x1f;

+

+      //

+      // Software must not assume any "level type" encoding 

+      // value to be related to any sub-leaf index, except sub-leaf 0.

+      //

+      SubIndex = 1;

+      do {

+        AsmCpuidEx (EFI_CPUID_EXTENDED_TOPOLOGY, SubIndex, &RegEax, NULL, &RegEcx, NULL);

+        LevelType = (RegEcx >> 8) & 0xff;

+        if (LevelType == EFI_CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE) {

+          CoreBits = (RegEax & 0x1f) - ThreadBits;

+          break;

+        }

+        SubIndex++;

+      } while (LevelType != EFI_CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID);

+    }

+  }

+

+  if (!TopologyLeafSupported) {

+    AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);

+    MaxLogicProcessorsPerPackage = (RegEbx >> 16) & 0xff;

+    if (MaxCpuIdIndex >= EFI_CPUID_CACHE_PARAMS) {

+      AsmCpuidEx (EFI_CPUID_CACHE_PARAMS, 0, &RegEax, NULL, NULL, NULL);

+      MaxCoresPerPackage = (RegEax >> 26) + 1;

+    } else {

+      //

+      // Must be a single-core processor.

+      //

+      MaxCoresPerPackage = 1;

+    }

+

+    ThreadBits = (UINTN) (HighBitSet32 (MaxLogicProcessorsPerPackage / MaxCoresPerPackage - 1) + 1);

+    CoreBits = (UINTN) (HighBitSet32 (MaxCoresPerPackage - 1) + 1);

+  }

+

+  Location->Thread  = InitialApicId & ~((-1) << ThreadBits);

+  Location->Core    = (InitialApicId >> ThreadBits) & ~((-1) << CoreBits);

+  Location->Package = (InitialApicId >> (ThreadBits+ CoreBits));

+  *ThreadIdBits     = ThreadBits;

+  *CoreIdBits       = CoreBits;

+}

+

+/**

+  Collects physical location of the processor.

+

+  This function collects physical location of the processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor

+

+**/

+VOID

+CollectProcessorLocation (

+  UINTN    ProcessorNumber

+  )

+{

+  CPU_COLLECTED_DATA  *CpuCollectedData;

+  UINT32              InitialApicID;

+  UINTN               ThreadIdBits;

+  UINTN               CoreIdBits;

+

+  CpuCollectedData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber];

+  InitialApicID    = CpuCollectedData->CpuMiscData.InitialApicID;

+

+  ExtractProcessorLocation (

+    InitialApicID,

+    &CpuCollectedData->ProcessorLocation,

+    &ThreadIdBits,

+    &CoreIdBits

+    );

+

+  CpuCollectedData->PackageIdBitOffset = (UINT8)(ThreadIdBits+ CoreIdBits);

+

+  //

+  // Check CMP and HT capabilities

+  //

+  if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {

+    if (CoreIdBits > 0) {

+      CmpCapable = TRUE;

+    }

+    if (ThreadIdBits > 0) {

+      HtCapable = TRUE;

+    }

+  }

+}

+

+/**

+  Collects intended FSB frequency and core to bus ratio.

+

+  This function collects intended FSB frequency and core to bus ratio.

+

+  @param  ProcessorNumber    Handle number of specified logical processor

+

+**/

+VOID

+CollectFrequencyData (

+  UINTN    ProcessorNumber

+  )

+{

+  CPU_MISC_DATA          *CpuMiscData;

+  UINT32                 FamilyId;

+  UINT32                 ModelId;

+  UINT32                 SteppingId;

+  BOOLEAN                OldInterruptState;

+  UINT64                 BeginValue;

+  UINT64                 EndValue;

+  UINT64                 ActualFrequency;

+  UINT64                 ActualFsb;

+

+  CpuMiscData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber].CpuMiscData;

+  CpuMiscData->FrequencyLocked = FALSE;

+  CpuMiscData->MaxCoreToBusRatio = (UINTN) 0x01;

+

+  GetProcessorVersionInfo (ProcessorNumber, &FamilyId, &ModelId, &SteppingId, NULL);

+

+  switch (FamilyId) {

+  case PENTIUM_FAMILY_ID:

+    switch (ModelId) {

+    case QUARK_MODEL_ID:

+      //

+      // Support for Pentium processor family

+      //

+

+      //

+      // Collect intended FSB frequency

+      //

+      CpuMiscData->IntendedFsbFrequency = 400;

+

+      //

+      // Check whether frequency is locked

+      //

+      CpuMiscData->FrequencyLocked = TRUE;

+

+      //

+      // Collect core to bus ratio

+      //

+      CpuMiscData->MaxCoreToBusRatio = (UINTN) 0x01;

+      CpuMiscData->MinCoreToBusRatio = (UINTN) 0x01;

+

+      //

+      // Collect VID

+      //

+      CpuMiscData->MaxVid = (UINTN) 0x03;

+      CpuMiscData->MinVid = (UINTN) 0x03;

+

+      break;

+

+    default:

+      break;

+    }

+    break;

+

+  default:

+    break;

+  }

+

+  //

+  // Calculate actual FSB frequency

+  // First calculate actual frequency by sampling some time and counts TSC

+  // Use spinlock mechanism because timer library cannot handle concurrent requests.

+  //

+  AcquireSpinLock (&mMPSystemData.APSerializeLock);

+  OldInterruptState = SaveAndDisableInterrupts ();

+  BeginValue  = AsmReadTsc ();

+  MicroSecondDelay (1000);

+  EndValue    = AsmReadTsc ();

+  SetInterruptState (OldInterruptState);

+  ReleaseSpinLock (&mMPSystemData.APSerializeLock);

+  //

+  // Calculate raw actual FSB frequency

+  //

+  ActualFrequency = DivU64x32 (EndValue - BeginValue, 1000);

+  ActualFsb = DivU64x32 (ActualFrequency, (UINT32) CpuMiscData->MaxCoreToBusRatio);

+  //

+  // Round the raw actual FSB frequency to standardized value

+  //

+  ActualFsb = ActualFsb + RShiftU64 (ActualFsb, 5);

+  ActualFsb = DivU64x32 (MultU64x32 (ActualFsb, 3), 100);

+  ActualFsb = DivU64x32 (MultU64x32 (ActualFsb, 100), 3);

+

+  CpuMiscData->ActualFsbFrequency = (UINTN) ActualFsb;

+

+  //

+  // Default number of P-states is 1

+  //

+  CpuMiscData->NumberOfPStates = 1;

+}

+

+/**

+  Collects capabilities of various features of the processor.

+

+  This function collects capabilities of various features of the processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor

+

+**/

+VOID

+CollectFeatureCapability (

+  UINTN    ProcessorNumber

+  )

+{

+  //

+  // Collect capability for Max CPUID Value Limit

+  //

+  if (FeaturePcdGet (PcdCpuMaxCpuIDValueLimitFlag)) {

+    MaxCpuidLimitDetect (ProcessorNumber);

+  }

+  //

+  // Collect capability for execute disable bit

+  //

+  if (FeaturePcdGet (PcdCpuExecuteDisableBitFlag)) {

+    XdDetect (ProcessorNumber);

+  }

+}

+

+/**

+  Collects basic processor data for calling processor.

+

+  This function collects basic processor data for calling processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+CollectBasicProcessorData (

+  IN UINTN  ProcessorNumber

+  )

+{

+  CPU_MISC_DATA        *CpuMiscData;

+

+  CpuMiscData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber].CpuMiscData;

+

+  if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {

+    //

+    // BIST for the BSP will be updated in CollectBistDataFromHob().

+    //

+    CpuMiscData->HealthData = 0;

+  } else {

+    CpuMiscData->HealthData = mExchangeInfo->BistBuffer[ProcessorNumber].Bist;

+  }

+

+  //

+  // A loop to check APIC ID and processor number

+  //

+  CollectApicData (ProcessorNumber);

+

+  //

+  // Get package number, core number and thread number.

+  //

+  CollectProcessorLocation (ProcessorNumber);

+}

+

+/**

+  Collects processor data for calling processor.

+

+  This function collects processor data for calling processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+CollectProcessorData (

+  IN UINTN  ProcessorNumber

+  )

+{

+  CPU_MISC_DATA        *CpuMiscData;

+

+  CpuMiscData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber].CpuMiscData;

+

+  //

+  // Collect all leafs for CPUID after second time microcode load.

+  //

+  CollectCpuidLeafs (ProcessorNumber);

+

+  //

+  // Get intended FSB frequency and core to bus ratio

+  //

+  CollectFrequencyData (ProcessorNumber);

+

+  //

+  // Collect capabilities for various features.

+  //

+  CollectFeatureCapability (ProcessorNumber);

+}

+

+/**

+  Checks the number of CPUID leafs need by a processor.

+

+  This function check the number of CPUID leafs need by a processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+CountNumberOfCpuidLeafs (

+  IN UINTN  ProcessorNumber

+  )

+{

+  UINT32               MaxCpuidIndex;

+  UINT32               MaxExtendedCpuidIndex;

+  UINT32               NumberOfCacheAndTlbRecords;

+  UINT32               NumberOfDeterministicCacheParametersLeafs;

+  UINT32               NumberOfExtendedTopologyEnumerationLeafs;

+  UINT32               RegValue;

+  CPU_COLLECTED_DATA   *CpuCollectedData;

+

+  CpuCollectedData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber];

+

+  //

+  // Get the max index of basic CPUID

+  //

+  AsmCpuid (0, &MaxCpuidIndex, NULL, NULL, NULL);

+  //

+  // Get the max index of extended CPUID

+  //

+  AsmCpuid (0x80000000, &MaxExtendedCpuidIndex, NULL, NULL, NULL);

+  //

+  // Get the number of cache and TLB CPUID leafs

+  //

+  AsmCpuid (2, &NumberOfCacheAndTlbRecords, NULL, NULL, NULL);

+  NumberOfCacheAndTlbRecords = NumberOfCacheAndTlbRecords & 0xff;

+

+  //

+  // Get the number of deterministic cache parameter CPUID leafs

+  //

+  NumberOfDeterministicCacheParametersLeafs = 0;

+  do {

+    AsmCpuidEx (4, NumberOfDeterministicCacheParametersLeafs++, &RegValue, NULL, NULL, NULL);

+  } while ((RegValue & 0x0f) != 0);

+

+  //

+  // Get the number of Extended Topology Enumeration CPUID leafs

+  //

+  NumberOfExtendedTopologyEnumerationLeafs = 0;

+  if (MaxCpuidIndex >= EFI_CPUID_CORE_TOPOLOGY) {

+    do {

+      AsmCpuidEx (EFI_CPUID_CORE_TOPOLOGY, NumberOfExtendedTopologyEnumerationLeafs++, NULL, &RegValue, NULL, NULL);

+    } while ((RegValue & 0x0FFFF) != 0);

+  }

+

+  //

+  // Save collected data in Processor Configuration Context Buffer

+  //

+  CpuCollectedData->CpuidData.NumberOfBasicCpuidLeafs                        = MaxCpuidIndex + 1;

+  CpuCollectedData->CpuidData.NumberOfExtendedCpuidLeafs                     = (MaxExtendedCpuidIndex - 0x80000000) + 1;

+  CpuCollectedData->CpuidData.NumberOfCacheAndTlbCpuidLeafs                  = NumberOfCacheAndTlbRecords;

+  CpuCollectedData->CpuidData.NumberOfDeterministicCacheParametersCpuidLeafs = NumberOfDeterministicCacheParametersLeafs;

+  CpuCollectedData->CpuidData.NumberOfExtendedTopologyEnumerationLeafs       = NumberOfExtendedTopologyEnumerationLeafs;

+}

+

+/**

+  Checks the number of CPUID leafs of all logical processors, and allocate memory for them.

+

+  This function checks the number of CPUID leafs of all logical processors, and allocates memory for them.

+

+**/

+VOID

+AllocateMemoryForCpuidLeafs (

+  VOID

+  )

+{

+  CPU_COLLECTED_DATA   *CpuCollectedData;

+  UINTN                ProcessorNumber;

+  UINTN                NumberOfLeafs;

+

+  //

+  // Wakeup all APs for CPUID checking.

+  //

+  DispatchAPAndWait (

+    TRUE,

+    0,

+    CountNumberOfCpuidLeafs

+    );

+  //

+  // Check number of CPUID leafs for BSP.

+  // Try to accomplish in first wakeup, and MTRR.

+  //

+  CountNumberOfCpuidLeafs (mCpuConfigConextBuffer.BspNumber);

+

+  //

+  // Allocate memory for CPUID leafs of all processors

+  //

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+

+    CpuCollectedData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber];

+

+    //

+    // Get the number of basic CPUID leafs.

+    //

+    NumberOfLeafs = CpuCollectedData->CpuidData.NumberOfBasicCpuidLeafs;

+    //

+    // Get the number of extended CPUID leafs.

+    //

+    NumberOfLeafs += CpuCollectedData->CpuidData.NumberOfExtendedCpuidLeafs;

+    //

+    // Get the number of cache and TLB CPUID leafs.

+    //

+    NumberOfLeafs += CpuCollectedData->CpuidData.NumberOfCacheAndTlbCpuidLeafs - 1;

+    //

+    // Get the number of deterministic cache parameters CPUID leafs.

+    //

+    NumberOfLeafs += CpuCollectedData->CpuidData.NumberOfDeterministicCacheParametersCpuidLeafs;

+    //

+    // Get the number of Extended Topology Enumeration CPUID leafs

+    //

+    NumberOfLeafs += CpuCollectedData->CpuidData.NumberOfExtendedTopologyEnumerationLeafs;

+

+    CpuCollectedData->CpuidData.CpuIdLeaf = AllocateZeroPool (sizeof (EFI_CPUID_REGISTER) * NumberOfLeafs);

+  }

+}

+

+/**

+  Collects BIST data from HOB.

+

+  This function collects BIST data from HOB built by SEC_PLATFORM_PPI.

+

+**/

+VOID

+CollectBistDataFromHob (

+  VOID

+  )

+{

+  EFI_HOB_GUID_TYPE       *GuidHob;

+  UINT32                  *DataInHob;

+  UINTN                   NumberOfData;

+  UINTN                   ProcessorNumber;

+  UINT32                  InitialLocalApicId;

+  CPU_MISC_DATA           *CpuMiscData;

+

+  GuidHob = GetFirstGuidHob (&gEfiHtBistHobGuid);

+  if (GuidHob == NULL) {

+    return;

+  }

+

+  DataInHob    = GET_GUID_HOB_DATA (GuidHob);

+  NumberOfData = GET_GUID_HOB_DATA_SIZE (GuidHob) / sizeof (UINT32);

+

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+    InitialLocalApicId = GetInitialLocalApicId (ProcessorNumber);

+    if (InitialLocalApicId < NumberOfData) {

+      CpuMiscData = &mCpuConfigConextBuffer.CollectedDataBuffer[ProcessorNumber].CpuMiscData;

+      CpuMiscData->HealthData = DataInHob[InitialLocalApicId];

+      //

+      // Initialize CPU health status for MP Services Protocol according to BIST data.

+      //

+      mMPSystemData.CpuHealthy[ProcessorNumber] = (BOOLEAN) (CpuMiscData->HealthData == 0);

+      if (!mMPSystemData.CpuHealthy[ProcessorNumber]) {

+        //

+        // Report Status Code that self test is failed

+        //

+        REPORT_STATUS_CODE (

+          EFI_ERROR_CODE | EFI_ERROR_MAJOR,

+          (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST)

+          );        

+      }

+    }

+  }

+}

+

+/**

+  Collects data from all logical processors.

+

+  This function collects data from all logical processors.

+

+**/

+VOID

+DataCollectionPhase (

+  VOID

+  )

+{

+  UINT8                     CallbackSignalValue;

+

+  //

+  // Set PcdCpuCallbackSignal to trigger callback function, and reads the value back.

+  //

+  CallbackSignalValue = SetAndReadCpuCallbackSignal (CPU_DATA_COLLECTION_SIGNAL);

+  //

+  // Check whether the callback function requests to bypass Setting phase.

+  //

+  if (CallbackSignalValue == CPU_BYPASS_SIGNAL) {

+    return;

+  }

+

+  //

+  // Check the number of CPUID leafs of all logical processors, and allocate memory for them.

+  //

+  AllocateMemoryForCpuidLeafs ();

+

+  //

+  // Wakeup all APs for data collection.

+  //

+  DispatchAPAndWait (

+    TRUE,

+    0,

+    CollectProcessorData

+    );

+

+  //

+  // Collect data for BSP.

+  //

+  CollectProcessorData (mCpuConfigConextBuffer.BspNumber);

+

+  CollectBistDataFromHob ();

+

+  //

+  // Set PCD data for HT and CMP information

+  //

+  if (CmpCapable) {

+    PcdSet32 (PcdCpuProcessorFeatureCapability, PcdGet32 (PcdCpuProcessorFeatureCapability) | PCD_CPU_CMP_BIT);

+    if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_CMP_BIT) != 0) {

+      PcdSet32 (PcdCpuProcessorFeatureSetting, PcdGet32 (PcdCpuProcessorFeatureSetting) | PCD_CPU_CMP_BIT);

+    }

+  }

+  if (HtCapable) {

+    PcdSet32 (PcdCpuProcessorFeatureCapability, PcdGet32 (PcdCpuProcessorFeatureCapability) | PCD_CPU_HT_BIT);

+    if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_HT_BIT) != 0) {

+      PcdSet32 (PcdCpuProcessorFeatureSetting, PcdGet32 (PcdCpuProcessorFeatureSetting) | PCD_CPU_HT_BIT);

+    }

+  }

+}

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Feature.h b/IA32FamilyCpuBasePkg/CpuMpDxe/Feature.h
new file mode 100644
index 0000000..60720b9
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Feature.h
@@ -0,0 +1,43 @@
+/** @file

+

+  Header file for processor features

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  Feature.h

+

+**/

+

+#ifndef _CPU_FEATURE_H_

+#define _CPU_FEATURE_H_

+

+#include "LimitCpuIdValue.h"

+#include "Xd.h"

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecific.c b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecific.c
new file mode 100644
index 0000000..cf0aacd
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecific.c
@@ -0,0 +1,143 @@
+/** @file

+

+  Memory Operation Functions for IA32 Architecture.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  ArchSpecific.c

+

+**/

+

+#include "Cpu.h"

+#include "MpService.h"

+

+MP_CPU_EXCHANGE_INFO    *mExchangeInfo;

+

+/**

+  Prepares Startup Vector for APs.

+

+  This function prepares Startup Vector for APs.

+

+**/

+VOID

+PrepareAPStartupVector (

+  VOID

+  )

+{

+  MP_ASSEMBLY_ADDRESS_MAP                     AddressMap;

+

+  //

+  // Get the address map of startup code for AP,

+  // including code size, and offset of long jump instructions to redirect.

+  //

+  AsmGetAddressMap (&AddressMap);

+

+  //

+  // Allocate a 4K-aligned region under 1M for startup vector for AP.

+  // The region contains AP startup code and exchange data between BSP and AP.

+  //

+  AllocateStartupVector (AddressMap.Size + sizeof (MP_CPU_EXCHANGE_INFO));

+

+  //

+  // Copy AP startup code to startup vector, and then redirect the long jump

+  // instructions for mode switching.

+  //

+  CopyMem ((VOID *) (UINTN) mStartupVector, AddressMap.RendezvousFunnelAddress, AddressMap.Size);

+  RedirectFarJump (&AddressMap, mStartupVector);

+

+  //

+  // Get the start address of exchange data between BSP and AP.

+  //

+  mExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mStartupVector + AddressMap.Size);

+

+  ZeroMem ((VOID *) mExchangeInfo, sizeof (MP_CPU_EXCHANGE_INFO));

+

+  PrepareGdtIdtForAP (

+    (IA32_DESCRIPTOR *) (UINTN) &mExchangeInfo->GdtrProfile,

+    (IA32_DESCRIPTOR *) (UINTN) &mExchangeInfo->IdtrProfile

+    );

+

+  //

+  // Assign ApLoopMode during POST phase

+  // Set ApLoopMode to ApInHltLoop if ApLoopMode is ApInMwaitLoop

+  // because ApInMwaitLoop could be supported only after C-State enabled.

+  //

+  if (PcdGet8 (PcdCpuApLoopMode) != ApInMwaitLoop) {

+    mExchangeInfo->ApLoopMode = (AP_LOOP_MODE) (PcdGet8 (PcdCpuApLoopMode));

+  } else {

+    mExchangeInfo->ApLoopMode = ApInHltLoop;

+  }

+

+  mExchangeInfo->ApFunction  = ApProcEntry;

+  mExchangeInfo->BufferStart = (UINT32) mStartupVector;

+  mExchangeInfo->InitFlag    = 1;

+}

+

+/**

+  Sets specified IDT entry with given function pointer.

+

+  This function sets specified IDT entry with given function pointer.

+

+  @param  FunctionPointer  Function pointer for IDT entry.

+  @param  IdtEntry         The IDT entry to update.

+

+  @return The original IDT entry value.

+

+**/

+UINTN

+SetIdtEntry (

+  IN  UINTN                       FunctionPointer,

+  OUT INTERRUPT_GATE_DESCRIPTOR   *IdtEntry

+)

+{

+  UINTN  OriginalEntry;

+

+  OriginalEntry = ((UINT32) IdtEntry->OffsetHigh << 16) + IdtEntry->OffsetLow;

+

+  IdtEntry->OffsetLow  = (UINT16) FunctionPointer;

+  IdtEntry->OffsetHigh = (UINT16) (FunctionPointer >> 16);

+

+  return OriginalEntry;

+}

+

+ /**

+  Fixup jump instructions in the AP startup code.

+

+  @param AddressMap    Pointer to MP_ASSEMBLY_ADDRESS_MAP.

+  @param TargetBuffer  Target address of the startup vector.

+**/

+VOID

+RedirectFarJump (

+  IN MP_ASSEMBLY_ADDRESS_MAP *AddressMap,

+  IN EFI_PHYSICAL_ADDRESS    TargetBuffer

+  )

+{

+  *(UINT32 *)(UINTN)(mStartupVector + AddressMap->FlatJumpOffset + 3) = (UINT32)(TargetBuffer + AddressMap->PModeEntryOffset);

+}

+

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecificDef.h b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecificDef.h
new file mode 100644
index 0000000..1669231
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/ArchSpecificDef.h
@@ -0,0 +1,84 @@
+/** @file

+

+Copyright (c) 2013 Intel Corporation.

+

+Redistribution and use in source and binary forms, with or without

+modification, are permitted provided that the following conditions

+are met:

+

+* Redistributions of source code must retain the above copyright

+notice, this list of conditions and the following disclaimer.

+* Redistributions in binary form must reproduce the above copyright

+notice, this list of conditions and the following disclaimer in

+the documentation and/or other materials provided with the

+distribution.

+* Neither the name of Intel Corporation nor the names of its

+contributors may be used to endorse or promote products derived

+from this software without specific prior written permission.

+

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+

+Module Name:

+

+  ProcessorDef.h

+

+Abstract:

+

+  Definition for IA32 processor

+

+**/

+

+#ifndef _PROCESSOR_DEF_H_

+#define _PROCESSOR_DEF_H_

+

+#include <FrameworkDxe.h>

+#include <Protocol/Cpu.h>

+

+#pragma pack(1)

+

+typedef struct {

+  UINT16  OffsetLow;

+  UINT16  SegmentSelector;

+  UINT16  Attributes;

+  UINT16  OffsetHigh;

+} INTERRUPT_GATE_DESCRIPTOR;

+

+#pragma pack()

+

+typedef struct {

+  VOID  *Start;

+  UINTN Size;

+  UINTN FixOffset;

+} INTERRUPT_HANDLER_TEMPLATE_MAP;

+

+typedef struct {

+  UINT8 *RendezvousFunnelAddress;

+  UINTN PModeEntryOffset;

+  UINTN FlatJumpOffset;

+  UINTN Size;

+} MP_ASSEMBLY_ADDRESS_MAP;

+

+/**

+  Get starting address and size of the rendezvous entry for APs.

+  Information for fixing a jump instruction in the code is also returned.

+

+  @param AddressMap  Output buffer for address map information.

+**/

+VOID

+EFIAPI

+AsmGetAddressMap (

+  OUT MP_ASSEMBLY_ADDRESS_MAP    *AddressMap

+  );

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/AsmInclude.inc b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/AsmInclude.inc
new file mode 100644
index 0000000..b384273
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/AsmInclude.inc
@@ -0,0 +1,59 @@
+;******************************************************************************

+;*

+;*    Copyright (c) 2013 Intel Corporation.

+;*

+;*    Redistribution and use in source and binary forms, with or without

+;*    modification, are permitted provided that the following conditions

+;*    are met:

+;*

+;*    * Redistributions of source code must retain the above copyright

+;*    notice, this list of conditions and the following disclaimer.

+;*    * Redistributions in binary form must reproduce the above copyright

+;*    notice, this list of conditions and the following disclaimer in

+;*    the documentation and/or other materials provided with the

+;*    distribution.

+;*    * Neither the name of Intel Corporation nor the names of its

+;*    contributors may be used to endorse or promote products derived

+;*    from this software without specific prior written permission.

+;*

+;*    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+;*    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+;*    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+;*    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+;*    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+;*    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+;*    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+;*    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+;*    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+;*    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+;*    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+;*

+;******************************************************************************

+

+VacantFlag          Equ   00h

+NotVacantFlag       Equ   0ffh

+StartupApSignal     Equ   6E750000h

+MonitorFilterSize   Equ   10h

+ApInHltLoop         Equ   1

+ApInMwaitLoop       Equ   2

+ApInRunLoop         Equ   3

+

+LockLocation        equ        (RendezvousFunnelProcEnd - RendezvousFunnelProcStart)

+StackStart          equ        (LockLocation + 4h)

+StackSize           equ        (LockLocation + 8h)

+RendezvousProc      equ        (LockLocation + 0Ch)

+GdtrProfile         equ        (LockLocation + 10h)

+IdtrProfile         equ        (LockLocation + 16h)

+BufferStart         equ        (LockLocation + 1Ch)

+Cr3Location         equ        (LockLocation + 20h)

+InitFlag            equ        (LockLocation + 24h)

+ApCountLocation     equ        (LockLocation + 28h)

+ApLoopModeLocation  equ        (LockLocation + 2Ch)

+BistBuffer          equ        (LockLocation + 30h)

+

+PAUSE32   MACRO

+            DB      0F3h

+            DB      090h

+            ENDM

+

+;-------------------------------------------------------------------------------

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.S b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.S
new file mode 100644
index 0000000..0d39d31
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.S
@@ -0,0 +1,56 @@
+#------------------------------------------------------------------------------

+#

+# Copyright (c) 2013 Intel Corporation.

+#

+# Redistribution and use in source and binary forms, with or without

+# modification, are permitted provided that the following conditions

+# are met:

+#

+# * Redistributions of source code must retain the above copyright

+# notice, this list of conditions and the following disclaimer.

+# * Redistributions in binary form must reproduce the above copyright

+# notice, this list of conditions and the following disclaimer in

+# the documentation and/or other materials provided with the

+# distribution.

+# * Neither the name of Intel Corporation nor the names of its

+# contributors may be used to endorse or promote products derived

+# from this software without specific prior written permission.

+#

+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+#

+# Module Name:

+#

+#   CpuAsm.S

+# 

+# Abstract:

+# 

+#   Assembly code that supports IA32 CPU architectural protocol

+#

+#------------------------------------------------------------------------------

+

+ASM_GLOBAL ASM_PFX(ApMachineCheckHandler)

+ASM_PFX(ApMachineCheckHandler):

+  #

+  # Clear MCIP flag of IA32_MCG_STATUS register

+  #

+  movl    $0x17a,%ecx

+  rdmsr

+  btrl    $2,%eax

+  wrmsr

+

+  iret

+

+ASM_GLOBAL ASM_PFX(ApMachineCheckHandlerEnd)

+

+ASM_PFX(ApMachineCheckHandlerEnd):

+

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.asm b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.asm
new file mode 100644
index 0000000..badbc23
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuAsm.asm
@@ -0,0 +1,69 @@
+  page    ,132

+  title   CPU ARCHITECTURAL DXE PROTOCOL ASSEMBLY HOOKS

+;------------------------------------------------------------------------------

+;

+; Copyright (c) 2013 Intel Corporation.

+;

+; Redistribution and use in source and binary forms, with or without

+; modification, are permitted provided that the following conditions

+; are met:

+;

+; * Redistributions of source code must retain the above copyright

+; notice, this list of conditions and the following disclaimer.

+; * Redistributions in binary form must reproduce the above copyright

+; notice, this list of conditions and the following disclaimer in

+; the documentation and/or other materials provided with the

+; distribution.

+; * Neither the name of Intel Corporation nor the names of its

+; contributors may be used to endorse or promote products derived

+; from this software without specific prior written permission.

+;

+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+;

+; Module Name:

+;

+;   CpuAsm.asm

+; 

+; Abstract:

+; 

+;   Assembly code that supports IA32 CPU architectural protocol

+;

+;------------------------------------------------------------------------------

+

+.686p

+.model  flat        

+

+.stack

+.code

+.MMX

+.XMM

+

+ApMachineCheckHandler    PROC C    PUBLIC

+  ;

+  ; Clear MCIP flag of IA32_MCG_STATUS register

+  ;

+  mov     ecx, 17ah

+  rdmsr

+  btr     eax, 2

+  wrmsr

+

+  iretd

+  

+ApMachineCheckHandler ENDP

+

+EXTERNDEF C ApMachineCheckHandlerEnd:BYTE

+

+ApMachineCheckHandlerEnd LABEL BYTE

+

+  end

+

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.c b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.c
new file mode 100644
index 0000000..f938baa
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.c
@@ -0,0 +1,52 @@
+/** @file                                                          

+

+  Code for cpu only reset.                                

+                                                                   

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+                                                                   

+  Module Name:  CpuOnlyReset.c                                  

+                                                                   

+**/

+

+#include "CpuOnlyReset.h"

+

+/**

+  Initiate CPU only reset.

+  

+  This function will save CPU context, call SetJump to mark the resume pointer

+  and program MCH to trigger CPU only reset.

+

+**/

+VOID

+InitiateCpuOnlyReset(

+  VOID

+  )

+{

+	return; 

+}

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.h b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.h
new file mode 100644
index 0000000..701d4ee
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/CpuOnlyReset.h
@@ -0,0 +1,184 @@
+/** @file                                                          

+

+  Header file for cpu only reset.                                

+                                                                   

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+                                                                   

+  Module Name:  CpuOnlyReset.h                                  

+                                                                   

+**/

+#ifndef _CPU_ONLY_RESET_H_

+#define _CPU_ONLY_RESET_H_

+

+#include "MpCommon.h"

+

+#define  CPU_ONLY_RESET_INDICATOR   SIGNATURE_32('C','R','S','T')

+#define  CPU_ONLY_RESET_TEMP_STACK_SIZE       128

+#pragma pack(1)

+//

+// This structure describe the mininal information SEC phase need  to deal with 

+// CPU only reset. 

+//

+typedef struct _CPU_ONLY_RESET_INFO_ {

+  UINT32                     CpuOnlyResetIndicator;  // a flag to indicate the reset is CPU only reset

+  UINT32                     EntryPoint;           // entry pointer SEC should jump to

+  UINT32                     NewStack;             // a temporary stack for the entry point

+  UINT32                     Checksum;             // the checksum to this data structure

+}CPU_ONLY_RESET_INFO;

+#pragma pack()

+

+#pragma pack(1)

+//

+// This data structure defined the trampolean information to resume to 64-bit 

+// code from CPU only reset. And this data structure will works as stack, so please

+// take care the fields' sequence and alignment when modification  

+// This structure is specific for 64-bit long mode

+//

+typedef struct _CPU_ONLY_RESET_TRAMPOLINE_INFO_ {

+  CPU_ONLY_RESET_INFO        CpuOnlyResetInfo;

+  //

+  // ASSUMPTION: 

+  // The gdt DXE drivers use, page table and CPU driver itself should 

+  // be located bellow 4G memory. in feature, when this stuff allows to locate 

+  // above 4G, the temporary page table, entry point and gdt

+  // need be implemented below 4G.

+  //

+  UINT16                     TemporaryGdtLimit;

+  UINT32                     TemporaryGdtBase;

+  // to make sure following field aligned with 4 bytes                   

+  UINT16                     Reserved0;

+  

+  UINT32                     TemporaryCR3;   

+  //

+  // prepare the parameter for calling InternalX86EnablePaging64 according to

+  // C calling convention to switch to long mode. 

+  //

+  //  InternalX86EnablePaging64 (

+  //   IN      UINT16                    Cs,

+  //   IN      UINT64                    EntryPoint,

+  //   IN      UINT64                    Context1,  OPTIONAL

+  //   IN      UINT64                    Context2,  OPTIONAL

+  //   IN      UINT64                    NewStack

+  //   );

+  //

+  // 4 bytes reserve for return address after call into  InternalX86EnablePaging64

+  // 

+  UINT32                    Reserved1;  

+  UINT16                    TemporaryCS;

+  UINT16                    Reserved2; // for alignment reason

+  UINT64                    CpuOnlyResetEntryPoint;

+  UINT64                    Context1;

+  UINT64                    Context2;

+  UINT64                    NewStack;

+  UINT8                     TemporaryStack[CPU_ONLY_RESET_TEMP_STACK_SIZE];

+} CPU_ONLY_RESET_TRAMPOLINE_INFO;

+

+#pragma pack()

+

+#define  CPU_ONLY_RESET_TRAMPOLINE_INFO_SIZE   sizeof(CPU_ONLY_RESET_TRAMPOLINE_INFO)  

+

+//

+// When CPU only reset occurs, we need save CPU_ONLY_RESET_TRAMPOLINE_INFO

+// to a well-known address which should be availabe and under 4G memory.

+// here we defines it as zero

+//

+#define  CPU_ONLY_RESET_TRAMPOLINE_INFO_BASE_ADDRESS      0x400

+

+//

+// the structure define is generic. it will be the same one no matter 

+// for 32-bit mode or 64-bit mode

+//

+typedef struct _CPU_ONLY_RESET_CONTEXT_BUFFER_ {

+  //

+  // System register 

+  //

+  IA32_DESCRIPTOR           GdtDesc; 

+  IA32_DESCRIPTOR           IdtDesc;

+  UINT16                    Ldtr;

+  UINT16                    Es;

+  UINT16                    Cs;

+  UINT16                    Ss;

+  UINT16                    Ds;

+  UINT16                    Fs;

+  UINT16                    Gs;

+  //

+  //

+  UINTN                    Cr0;

+  UINTN                    Cr3;

+  UINTN                    Cr4;

+  UINTN                    Tr;

+  //

+  // debug register

+  //

+  UINTN                    Dr0;

+  UINTN                    Dr1;

+  UINTN                    Dr2;

+  UINTN                    Dr3;

+  UINTN                    Dr6;

+  UINTN                    Dr7;

+  //

+  // General register

+  //

+  BASE_LIBRARY_JUMP_BUFFER  JumpContext;     

+  //

+  // When CPU only reset occurs, we need save CPU_ONLY_RESET_TRAMPOLINE_INFO

+  // to a well-known address which should be under 4G memory(say address 0)

+  // So this field will save the original content on that address and 

+  // restore it after resume

+  //

+  UINT8                     CpuOnlyResetTrampolineInfo[CPU_ONLY_RESET_TRAMPOLINE_INFO_SIZE];        

+        

+}CPU_ONLY_RESET_CONTEXT_BUFFER;

+

+/**

+  Initiate CPU only reset.

+  

+  This function will save CPU context, call SetJump to mark the resume pointer

+  and program MCH to trigger CPU only reset.

+

+**/

+VOID

+InitiateCpuOnlyReset(

+  VOID

+  );

+/**

+  This function is written in Long mode instructions and build by 64-bit 

+  assembler, BUT running in 32-bit protected mode

+  This function is the real entry point after CPU only reset. SEC will dire

+

+  @param Context1   The first context save the info.

+  @param Context2   The second context save the info.

+**/

+VOID

+EFIAPI

+CpuOnlyResetResumeEntryWrapper (

+  VOID                 *Context1,

+  VOID                 *Context2

+  );

+#endif // _CPU_ONLY_RESET_H_

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/Exception.c b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/Exception.c
new file mode 100644
index 0000000..e9d1a00
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/Exception.c
@@ -0,0 +1,327 @@
+/** @file

+

+Copyright (c) 2013 Intel Corporation.

+

+Redistribution and use in source and binary forms, with or without

+modification, are permitted provided that the following conditions

+are met:

+

+* Redistributions of source code must retain the above copyright

+notice, this list of conditions and the following disclaimer.

+* Redistributions in binary form must reproduce the above copyright

+notice, this list of conditions and the following disclaimer in

+the documentation and/or other materials provided with the

+distribution.

+* Neither the name of Intel Corporation nor the names of its

+contributors may be used to endorse or promote products derived

+from this software without specific prior written permission.

+

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+Module Name:

+

+  Exception.c

+    

+Abstract:

+

+  IA-32 Exception Handler.

+

+**/

+

+#include "Cpu.h"

+#include "Exception.h"

+

+//

+// Error code flag indicating whether or not an error code will be 

+// pushed on the stack if an exception occurs.

+//

+// 1 means an error code will be pushed, otherwise 0

+//

+// bit 0 - exception 0

+// bit 1 - exception 1

+// etc.

+//

+UINT32 mErrorCodeFlag = 0x00027d00;

+

+//

+// Local Table

+//

+EFI_EXCEPTION_HANDLER mExceptionTable[] = {

+  {

+    EFI_SW_EC_IA32_DIVIDE_ERROR,

+    INTERRUPT_HANDLER_DIVIDE_ZERO

+  },

+  {

+    EFI_SW_EC_IA32_DEBUG,

+    INTERRUPT_HANDLER_DEBUG

+  },

+  {

+    EFI_SW_EC_IA32_NMI,

+    INTERRUPT_HANDLER_NMI

+  },

+  {

+    EFI_SW_EC_IA32_BREAKPOINT,

+    INTERRUPT_HANDLER_BREAKPOINT

+  },

+  {

+    EFI_SW_EC_IA32_OVERFLOW,

+    INTERRUPT_HANDLER_OVERFLOW

+  },

+  {

+    EFI_SW_EC_IA32_BOUND,

+    INTERRUPT_HANDLER_BOUND

+  },

+  {

+    EFI_SW_EC_IA32_INVALID_OPCODE,

+    INTERRUPT_HANDLER_INVALID_OPCODE

+  },

+  //

+  // Interrupt 7, 9, 15 not defined in the debug support protocol. Hence no status codes for them!

+  //

+  {

+    EFI_SW_EC_IA32_INVALID_TSS,

+    INTERRUPT_HANDLER_INVALID_TSS

+  },

+  {

+    EFI_SW_EC_IA32_SEG_NOT_PRESENT,

+    INTERRUPT_HANDLER_SEGMENT_NOT_PRESENT

+  },

+  {

+    EFI_SW_EC_IA32_STACK_FAULT,

+    INTERRUPT_HANDLER_STACK_SEGMENT_FAULT

+  },

+  {

+    EFI_SW_EC_IA32_GP_FAULT,

+    INTERRUPT_HANDLER_GP_FAULT

+  },

+  {

+    EFI_SW_EC_IA32_PAGE_FAULT,

+    INTERRUPT_HANDLER_PAGE_FAULT

+  },

+  {

+    EFI_SW_EC_IA32_FP_ERROR,

+    INTERRUPT_HANDLER_MATH_FAULT

+  },

+  {

+    EFI_SW_EC_IA32_ALIGNMENT_CHECK,

+    INTERRUPT_HANDLER_ALIGNMENT_FAULT

+  },

+  {

+    EFI_SW_EC_IA32_MACHINE_CHECK,

+    INTERRUPT_HANDLER_MACHINE_CHECK

+  },

+  {

+    EFI_SW_EC_IA32_SIMD,

+    INTERRUPT_HANDLER_STREAMING_SIMD

+  }

+};

+

+UINTN mExceptionNumber = sizeof (mExceptionTable) / sizeof (EFI_EXCEPTION_HANDLER);

+

+CPU_STATUS_CODE_TEMPLATE  mStatusCodeData  =  {

+  {

+    sizeof (EFI_STATUS_CODE_DATA),

+    sizeof (EFI_SYSTEM_CONTEXT_IA32),

+    { 0 }

+  },

+  {

+    0

+  }

+};

+

+/**

+  Reports StatusCode for Exception

+

+  This function reports status code for exception.

+

+  @param  InterruptType   Interrupt type

+  @param  SystemContext   EFI_SYSTEM_CONTEXT

+

+**/

+VOID

+ReportData (

+  IN EFI_EXCEPTION_TYPE   InterruptType, 

+  IN EFI_SYSTEM_CONTEXT   SystemContext

+  )

+{

+  UINT32                ErrorMessage;

+  UINT32                Index;

+

+  CopyMem (

+    &mStatusCodeData.SystemContext.SystemContextIa32,

+    SystemContext.SystemContextIa32,

+    sizeof (EFI_SYSTEM_CONTEXT_IA32)

+    );

+

+  ErrorMessage = EFI_SOFTWARE_DXE_BS_DRIVER;

+  for (Index = 0; Index < mExceptionNumber; Index++) {

+    if (mExceptionTable[Index].Interrupt == InterruptType) {

+      ErrorMessage |= mExceptionTable[Index].ErrorMessage;

+      break;

+    }

+  }

+

+  REPORT_STATUS_CODE_EX (

+    (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED),

+    EFI_SOFTWARE_UNSPECIFIED | ErrorMessage,

+    0,

+    NULL,

+    NULL,

+    (UINT8 *)&mStatusCodeData + sizeof (EFI_STATUS_CODE_DATA),

+    sizeof (EFI_SYSTEM_CONTEXT_IA32)

+    ); 

+}

+

+/**

+  Common exception handler.

+

+  @param InterruptType  Exception type.

+  @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.

+**/

+VOID

+EFIAPI

+CommonExceptionHandler (

+  IN EFI_EXCEPTION_TYPE   InterruptType,

+  IN EFI_SYSTEM_CONTEXT   SystemContext

+  )

+{

+  DEBUG ((

+    EFI_D_ERROR,

+    "!!!! IA32 Exception Type - %08x !!!!\n",

+    InterruptType

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "EIP - %08x, CS - %08x, EFLAGS - %08x\n",

+    SystemContext.SystemContextIa32->Eip,

+    SystemContext.SystemContextIa32->Cs,

+    SystemContext.SystemContextIa32->Eflags

+    ));

+  if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {

+    DEBUG ((

+      EFI_D_ERROR,

+      "ExceptionData - %08x\n",

+      SystemContext.SystemContextIa32->ExceptionData

+      ));

+  }

+  DEBUG ((

+    EFI_D_ERROR,

+    "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",

+    SystemContext.SystemContextIa32->Eax,

+    SystemContext.SystemContextIa32->Ecx,

+    SystemContext.SystemContextIa32->Edx,

+    SystemContext.SystemContextIa32->Ebx

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",

+    SystemContext.SystemContextIa32->Esp,

+    SystemContext.SystemContextIa32->Ebp,

+    SystemContext.SystemContextIa32->Esi,

+    SystemContext.SystemContextIa32->Edi

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",

+    SystemContext.SystemContextIa32->Ds,

+    SystemContext.SystemContextIa32->Es,

+    SystemContext.SystemContextIa32->Fs,

+    SystemContext.SystemContextIa32->Gs,

+    SystemContext.SystemContextIa32->Ss

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "GDTR - %08x %08x, IDTR - %08x %08x\n",

+    SystemContext.SystemContextIa32->Gdtr[0],

+    SystemContext.SystemContextIa32->Gdtr[1],

+    SystemContext.SystemContextIa32->Idtr[0],

+    SystemContext.SystemContextIa32->Idtr[1]

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "LDTR - %08x, TR - %08x\n",

+    SystemContext.SystemContextIa32->Ldtr,

+    SystemContext.SystemContextIa32->Tr

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",

+    SystemContext.SystemContextIa32->Cr0,

+    SystemContext.SystemContextIa32->Cr2,

+    SystemContext.SystemContextIa32->Cr3,

+    SystemContext.SystemContextIa32->Cr4

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",

+    SystemContext.SystemContextIa32->Dr0,

+    SystemContext.SystemContextIa32->Dr1,

+    SystemContext.SystemContextIa32->Dr2,

+    SystemContext.SystemContextIa32->Dr3

+    ));

+  DEBUG ((

+    EFI_D_ERROR,

+    "DR6 - %08x, DR7 - %08x\n",

+    SystemContext.SystemContextIa32->Dr6,

+    SystemContext.SystemContextIa32->Dr7

+    ));

+  

+  //

+  // Report Status Code

+  //

+  ReportData (InterruptType, SystemContext);

+  

+  //

+  // Enter a dead loop.

+  //

+  CpuDeadLoop ();

+

+  return ;

+}

+

+/**

+  Installs the Exception Handler.

+

+  This function installs the Exception Handler.

+

+**/

+VOID

+InitializeException (

+  VOID

+  )

+{

+  EFI_STATUS                      Status;

+  UINT32                          Index;

+  BOOLEAN                         OldInterruptState;

+

+  //

+  // Disable interrupt

+  //

+  OldInterruptState = SaveAndDisableInterrupts ();

+

+  for (Index = 0; Index < mExceptionNumber; Index++) {

+    //

+    // Register sample excception handler

+    //

+    Status = mCpuArchProtocol.RegisterInterruptHandler (

+                                 &mCpuArchProtocol, 

+                                 mExceptionTable[Index].Interrupt,

+                                 CommonExceptionHandler

+                                 );

+    ASSERT_EFI_ERROR (Status);

+  }

+  //

+  // Restore interrupt state.

+  //

+  SetInterruptState (OldInterruptState);

+}

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.S b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.S
new file mode 100644
index 0000000..ebf817b
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.S
@@ -0,0 +1,449 @@
+#-------------------------------------------------------------------------------

+#

+# Copyright (c) 2013 Intel Corporation.

+#

+# Redistribution and use in source and binary forms, with or without

+# modification, are permitted provided that the following conditions

+# are met:

+#

+# * Redistributions of source code must retain the above copyright

+# notice, this list of conditions and the following disclaimer.

+# * Redistributions in binary form must reproduce the above copyright

+# notice, this list of conditions and the following disclaimer in

+# the documentation and/or other materials provided with the

+# distribution.

+# * Neither the name of Intel Corporation nor the names of its

+# contributors may be used to endorse or promote products derived

+# from this software without specific prior written permission.

+#

+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+#

+#

+# Module Name:

+#

+#   MPFuncs32.S

+#

+# Abstract:

+#

+#   This is the assembly code for MP (Multiple-processor) support

+#

+#-------------------------------------------------------------------------------

+

+

+.equ                   VacantFlag,                0x0

+.equ                   NotVacantFlag,             0xff

+.equ                   StartupApSignal,           0x6E750000

+.equ                   MonitorFilterSize,         0x10

+.equ                   ApInHltLoop,               1

+.equ                   ApInMwaitLoop,             2

+.equ                   ApInRunLoop,               3

+

+

+.equ                   LockLocation,      RendezvousFunnelProcEnd - RendezvousFunnelProcStart

+.equ                   StackStart,        RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x04

+.equ                   StackSize,         RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x08

+.equ                   RendezvousProc,    RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x0C

+.equ                   GdtrProfile,       RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x10

+.equ                   IdtrProfile,       RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x16

+.equ                   BufferStart,       RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x1C

+.equ                   Cr3Location,       RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x20

+.equ                   InitFlag,          RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x24

+.equ                   ApCountLocation,   RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x28

+.equ                   ApLoopModeLocation,RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x2C

+.equ                   BistBuffer,        RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x30

+

+#-------------------------------------------------------------------------------------

+.macro  PAUSE32

+            .byte 0xF3

+            .byte 0x90

+.endm

+

+#-------------------------------------------------------------------------------------

+#RendezvousFunnelProc  procedure follows. All APs execute their procedure. This

+#procedure serializes all the AP processors through an Init sequence. It must be

+#noted that APs arrive here very raw...ie: real mode, no stack.

+#ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC

+#IS IN MACHINE CODE.

+#-------------------------------------------------------------------------------------

+#RendezvousFunnelProc (&WakeUpBuffer,MemAddress);

+

+ASM_GLOBAL ASM_PFX(RendezvousFunnelProc)

+ASM_PFX(RendezvousFunnelProc):

+RendezvousFunnelProcStart:

+

+

+# At this point CS = 0x(vv00) and ip= 0x0.

+

+        .byte 0x66,0x8b,0xe8          # mov        ebp, eax

+

+        .byte 0x8c,0xc8               # mov        ax,  cs

+        .byte 0x8e,0xd8               # mov        ds,  ax

+        .byte 0x8e,0xc0               # mov        es,  ax

+        .byte 0x8e,0xd0               # mov        ss,  ax

+        .byte 0x33,0xc0               # xor        ax,  ax

+        .byte 0x8e,0xe0               # mov        fs,  ax

+        .byte 0x8e,0xe8               # mov        gs,  ax

+

+# Get APIC ID

+

+        .byte 0x66,0xB8

+        .long 0x00000000              # mov        eax, 0

+        .byte 0x0F,0xA2               # cpuid

+        .byte 0x66,0x3d

+        .long 0x0000000B              # cmp        eax, 0b

+        .byte 0x73,0x0e               # jnb        X2Apic

+

+# Processor is not x2APIC capable, so get 8-bit APIC ID

+        .byte 0x66,0xB8               # mov        eax, 1

+        .long 0x00000001              # cpuid

+        .byte 0x0F,0xA2

+        .byte 0x66,0xC1,0xEB,0x18     # shr        ebx, 24

+        .byte 0xeb,0x0e               # jmp CheckInitFlag

+

+# Processor is x2APIC capable, so get 32-bit x2APIC ID

+X2Apic:

+        .byte 0x66,0xB8

+        .long 0x0000000B              # mov        eax, 0b

+        .byte 0x66,0x31,0xc9          # xor        ecx, ecx

+        .byte 0x0F,0xA2               # cpuid

+        .byte 0x66,0x89,0xd3          # mov        ebx, edx

+

+CheckInitFlag:

+# If it is the first time AP wakes up, just record AP's BIST

+# Otherwise, switch to flat mode

+

+        .byte 0xBE

+        .word InitFlag                # mov        si,  InitFlag

+        .byte 0x66,0x83,0x3C,0x0      # cmp        dword ptr [si], 0

+        .byte 0x74

+        .byte flat32Start - . - 1     # jz         flat32Start

+

+# Increase ApCount as processor number for index of BIST Info array

+

+        .byte 0x66,0xa1                  # mov        eax, [ApCountLocation]

+        .word ApCountLocation

+IncApCount:

+        .byte 0x66,0x67,0x8d,0x48,0x01   # lea        ecx, [eax+1]

+        .byte 0xf0,0x66,0x0f,0xb1,0x0e   # lock       cmpxchg [ApCountLocation], ecx

+        .word ApCountLocation

+        .byte 0x75,0xf2                  # jnz        IncApCount

+        .byte 0x66, 0xff, 0xc0           # inc        eax                         ; AP processor number starts from 1

+# Record BIST information

+#

+        .byte 0x66,0x67,0x8d,0x34,0xc5   # lea esi, [BistBuffer + eax*8]

+        .long BistBuffer

+

+        .byte 0x66,0x89,0x1c             # mov        dword ptr [si], ebx         ; APIC ID

+        .byte 0x66,0x89,0x6C,0x04        # mov        dword ptr [si + 4], ebp     ; Store BIST value

+

+        cli

+        hlt

+        jmp .-2

+

+# Switch to flat mode.

+

+flat32Start:

+

+        .byte 0xBE

+        .word BufferStart             # mov        si, BufferStart

+        .byte 0x66,0x8B,0x0C          # mov        ecx,dword ptr [si]          ; ECX is keeping the start address of wakeup buffer

+

+        .byte 0xFA                    # cli

+

+        .byte 0xBE

+        .word GdtrProfile             # mov        si, GdtrProfile

+        .byte 0x66                    # db         66h

+        .byte 0x2E,0xF,0x1,0x14       # lgdt       fword ptr cs:[si]

+

+        .byte 0xBE

+        .word IdtrProfile             # mov        si, IdtrProfile

+        .byte 0x66                    # db         66h

+        .byte 0x2E,0xF,0x1,0x1C       # lidt       fword ptr cs:[si]

+

+        .byte 0x33,0xC0               # xor        ax,  ax

+        .byte 0x8E,0xD8               # mov        ds,  ax

+

+        .byte 0xF,0x20,0xC0           # mov        eax, cr0                    ; Get control register 0

+        .byte 0x66,0x83,0xC8,0x1      # or         eax, 000000001h             ; Set PE bit (bit #0)

+        .byte 0xF,0x22,0xC0           # mov        cr0, eax

+

+

+#step-4:

+

+FLAT32_JUMP:

+

+        .byte 0x66,0x67,0xEA          # far jump

+        .long 0x0

+        .word 0x10

+

+PMODE_ENTRY:                          # protected mode entry point

+

+        movw        $0x8,%ax

+        .byte       0x66

+        movw        %ax,%ds

+        .byte       0x66

+        movw        %ax,%es

+        .byte       0x66

+        movw        %ax,%fs

+        .byte       0x66

+        movw        %ax,%gs

+        .byte       0x66

+        movw        %ax,%ss           # Flat mode setup.

+

+        movl        %ecx,%esi

+

+        movl        %esi,%edi

+        addl        $InitFlag, %edi

+        cmpl        $2, (%edi)

+        jz          ProgramDynamicStack

+

+ProgramStaticStack:

+

+        #

+        # Get processor number for this AP

+        # Note that BSP may become an AP due to SwitchBsp()

+        #

+        xorl        %ecx, %ecx

+        leal        BistBuffer(%esi), %edi

+

+GetProcNumber:

+        cmpl        %ebx, (%edi)                     # APIC ID match?

+        jz          Found

+        addl        $8, %edi

+        incl        %ecx

+        cmpl        ApCountLocation(%esi), %ecx

+        jbe         GetProcNumber

+

+Found:

+        #

+        # ProgramStack

+        #

+

+        movl        %esi, %edi

+        addl        $StackSize, %edi

+        movl        (%edi), %eax

+        incl        %ecx

+        mull        %ecx                              # EAX = StackSize * (CpuNumber + 1)

+        decl        %ecx

+

+        movl        %esi, %edi

+        addl        $StackStart, %edi

+        movl        (%edi), %ebx

+        addl        %ebx, %eax                        # EAX = StackStart + StackSize * (CpuNumber + 1)

+

+        movl        %eax, %esp

+        subl        $MonitorFilterSize, %esp          # Reserved Monitor data space

+        movl        %ecx, %ebp                        # Save processor number in ebp

+        jmp         ProgramStackDone

+

+ProgramDynamicStack:

+

+        movl        %esi,%edi

+        addl        $LockLocation, %edi

+        movb        $NotVacantFlag, %al

+TestLock:

+        xchgb       (%edi), %al

+        cmpb        $NotVacantFlag, %al

+        jz          TestLock

+

+        movl        %esi,%edi

+        addl        $StackSize, %edi

+        movl        (%edi), %eax

+        movl        %esi,%edi

+        addl        $StackStart, %edi

+        addl        (%edi), %eax

+        movl        %eax,%esp

+        movl        %eax, (%edi)

+

+Releaselock:

+        movb        $VacantFlag, %al

+        movl        %esi,%edi

+        addl        $LockLocation, %edi

+        xchgb       (%edi), %al

+

+ProgramStackDone:

+

+        #

+        # Call assembly function to initialize FPU.

+        #

+        lea         ASM_PFX(InitializeFloatingPointUnits), %ebx

+        call        *%ebx

+

+        #

+        # Call C Function

+        #

+        movl        %esi,%edi

+        addl        $RendezvousProc, %edi

+        addl        $ApLoopModeLocation, %esi         # esi = ApLoopMode address location

+

+        xorl        %ebx, %ebx                          

+        movl        %ebx, 0xC(%esp)                   # Clean ReadyToBoot Flag

+        movw        %bp, %bx                          # bx = the lowest 16bit of CpuNumber

+        orl         $StartupApSignal, %ebx            # Construct AP run Singal

+        

+WakeUpThisAp:

+        movl        (%edi), %eax

+        testl       %eax, %eax

+        jz          CheckReadyToBoot

+

+        push        %ebp

+        call        *%eax

+        addl        $4, %esp

+

+        #

+        # Check if BSP was switched

+        #

+        movl        ASM_PFX(mBspSwitched), %eax

+        cmpb        $0, (%eax)

+        jz          CheckReadyToBoot

+

+        movb        $0, (%eax)                    # clear BSP switch flag

+

+        movl        ASM_PFX(mNewProcessorNumber), %eax

+        movl        (%eax), %ebp                  # rbp = new processor number

+

+        movw        %bp, %bx                      # bx = the lowest 16bit of CpuNumber

+

+        #

+        # Assign the dedicated AP stack for the new AP

+        #

+        movl        ASM_PFX(mMonitorDataAddress), %eax

+        movl        (%eax), %esp

+

+CheckReadyToBoot:

+        movl        (%esi), %eax                  # eax = ApLoopMode for POST

+        cmpb        $1, 0xC(%esp)                 # Check ReadyToBoot flag?

+        jnz         CheckWakeUpManner

+

+        movl        $ApInHltLoop, %eax

+        cmpl        $1, 0xD(%esp)                 # Check if C-State enable?

+        jnz         CheckWakeUpManner

+

+        movl        ApInMwaitLoop, %eax           # eax = ApLoopMode for Read To Boot

+         

+CheckWakeUpManner:

+        cli

+        cmpl        $ApInHltLoop, %eax

+        jz          HltApLoop

+

+        cmpl        $ApInMwaitLoop, %eax

+        jnz         CheckRunSignal

+

+ApMwaitLoop:

+        movl        %esp, %eax                    # Set Monitor Address

+        xorl        %ecx, %ecx                    # ecx = 0

+        xorl        %edx, %edx                    # edx = 0

+        .byte       0x0f,0x1,0xc8                 # MONITOR

+

+        movl        4(%esp), %eax                 # Mwait Cx, Target C-State per eax[7:4]

+        .byte       0x0f,0x1,0xc9                 # MWAIT

+

+CheckRunSignal:

+        cmpl        %ebx, (%esp)                  # Check if run signal correct?

+        jz          WakeUpThisAp                  # Jmp to execute AP task

+        PAUSE32

+        jmp         CheckReadyToBoot              # Unknown break, go checking run manner

+

+HltApLoop:

+        cli

+        hlt

+        jmp         HltApLoop                     # Jump to halt loop

+

+RendezvousFunnelProcEnd:

+#-------------------------------------------------------------------------------------

+#  AsmGetAddressMap (&AddressMap);

+#-------------------------------------------------------------------------------------

+ASM_GLOBAL ASM_PFX(AsmGetAddressMap)

+ASM_PFX(AsmGetAddressMap):

+

+        pushal

+        movl        %esp,%ebp

+

+        movl        0x24(%ebp), %ebx

+        movl        $RendezvousFunnelProcStart, (%ebx)

+        movl        $(PMODE_ENTRY - RendezvousFunnelProcStart), 0x4(%ebx)

+        movl        $(FLAT32_JUMP - RendezvousFunnelProcStart), 0x8(%ebx)

+        movl        $(RendezvousFunnelProcEnd - RendezvousFunnelProcStart), 0x0c(%ebx)

+

+        popal

+        ret

+

+#-------------------------------------------------------------------------------------

+#AsmExchangeRole procedure follows. This procedure executed by current BSP, that is

+#about to become an AP. It switches it'stack with the current AP.

+#AsmExchangeRole (IN   CPU_EXCHANGE_INFO    *MyInfo, IN   CPU_EXCHANGE_INFO    *OthersInfo);

+#-------------------------------------------------------------------------------------

+.equ                           CPU_SWITCH_STATE_IDLE, 0

+.equ                           CPU_SWITCH_STATE_STORED, 1

+.equ                           CPU_SWITCH_STATE_LOADED, 2

+

+ASM_GLOBAL ASM_PFX(AsmExchangeRole)

+ASM_PFX(AsmExchangeRole):

+        # DO NOT call other functions in this function, since 2 CPU may use 1 stack

+        # at the same time. If 1 CPU try to call a functiosn, stack will be corrupted.

+        pushal

+        movl        %esp,%ebp

+

+        # esi contains MyInfo pointer

+        movl        0x24(%ebp), %esi

+

+        # edi contains OthersInfo pointer

+        movl        0x28(%ebp), %edi

+

+        #Store EFLAGS, GDTR and IDTR regiter to stack

+        pushfl

+        sgdt        8(%esi)

+        sidt        14(%esi)

+

+        # Store the its StackPointer

+        movl        %esp, 4(%esi)

+

+        # update its switch state to STORED

+        movb        $CPU_SWITCH_STATE_STORED, (%esi)

+

+WaitForOtherStored:

+        # wait until the other CPU finish storing its state

+        cmpb        $CPU_SWITCH_STATE_STORED, (%edi)

+        jz          OtherStored

+        pause

+        jmp         WaitForOtherStored

+

+OtherStored:

+        # Since another CPU already stored its state, load them

+        # load GDTR value

+        lgdt        8(%edi)

+

+        # load IDTR value

+        lidt        14(%edi)

+

+        # load its future StackPointer

+        movl        4(%edi), %esp

+

+        # update the other CPU's switch state to LOADED

+        movb        $CPU_SWITCH_STATE_LOADED, (%edi)

+

+WaitForOtherLoaded:

+        # wait until the other CPU finish loading new state,

+        # otherwise the data in stack may corrupt

+        cmpb        $CPU_SWITCH_STATE_LOADED, (%esi)

+        jz          OtherLoaded

+        pause

+        jmp         WaitForOtherLoaded

+

+OtherLoaded:

+        # since the other CPU already get the data it want, leave this procedure

+        popfl

+

+        popal

+        ret

+

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.asm b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.asm
new file mode 100644
index 0000000..a38e928
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/IA32/MpFuncs.asm
@@ -0,0 +1,440 @@
+;-------------------------------------------------------------------------------

+;

+; Copyright (c) 2013 Intel Corporation.

+;

+; Redistribution and use in source and binary forms, with or without

+; modification, are permitted provided that the following conditions

+; are met:

+;

+; * Redistributions of source code must retain the above copyright

+; notice, this list of conditions and the following disclaimer.

+; * Redistributions in binary form must reproduce the above copyright

+; notice, this list of conditions and the following disclaimer in

+; the documentation and/or other materials provided with the

+; distribution.

+; * Neither the name of Intel Corporation nor the names of its

+; contributors may be used to endorse or promote products derived

+; from this software without specific prior written permission.

+;

+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+;

+;

+; Module Name:

+;

+;   MPFuncs32.asm

+;

+; Abstract:

+;

+;   This is the assembly code for MP (Multiple-processor) support

+;

+;-------------------------------------------------------------------------------

+

+.686p

+.model  flat

+.code

+

+include AsmInclude.inc

+InitializeFloatingPointUnits PROTO C

+

+EXTERNDEF   C   mBspSwitched:BYTE

+EXTERNDEF   C   mNewProcessorNumber:DWORD

+EXTERNDEF   C   mMonitorDataAddress:DWORD

+

+;-------------------------------------------------------------------------------------

+FJMP32  MACRO   Selector, Offset

+            DB      066h

+            DB      067h

+            DB      0EAh            ; far jump

+            DD      Offset          ; 32-bit offset

+            DW      Selector        ; 16-bit selector

+            ENDM

+FCALL32 MACRO   Selector, Offset

+            DB      09Ah

+            DD      Offset          ; 32-bit offset

+            DW      Selector        ; 16-bit selector

+            ENDM

+;-------------------------------------------------------------------------------------

+;RendezvousFunnelProc  procedure follows. All APs execute their procedure. This

+;procedure serializes all the AP processors through an Init sequence. It must be

+;noted that APs arrive here very raw...ie: real mode, no stack.

+;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC

+;IS IN MACHINE CODE.

+;-------------------------------------------------------------------------------------

+;RendezvousFunnelProc (&WakeUpBuffer,MemAddress);

+

+RendezvousFunnelProc   PROC  near C  PUBLIC

+RendezvousFunnelProcStart::

+

+; At this point CS = 0x(vv00) and ip= 0x0.

+

+        db 66h,  08bh, 0e8h           ; mov        ebp, eax

+

+        db 8ch,  0c8h                 ; mov        ax,  cs

+        db 8eh,  0d8h                 ; mov        ds,  ax

+        db 8eh,  0c0h                 ; mov        es,  ax

+        db 8eh,  0d0h                 ; mov        ss,  ax

+        db 33h,  0c0h                 ; xor        ax,  ax

+        db 8eh,  0e0h                 ; mov        fs,  ax

+        db 8eh,  0e8h                 ; mov        gs,  ax

+

+; Get APIC ID

+

+        db 66h,  0B8h

+        dd 00000000h                  ; mov        eax, 0

+        db 0Fh,  0A2h                 ; cpuid

+        db 66h, 3dh

+        dd 0000000Bh                  ; cmp        eax, 0b

+        db 73h

+        db X2Apic - $ - 1             ; jnb        X2Apic

+

+; Processor is not x2APIC capable, so get 8-bit APIC ID

+        db 66h,  0B8h

+        dd 00000001h                  ; mov        eax, 1

+        db 0Fh,  0A2h                 ; cpuid

+        db 66h,  0C1h, 0EBh, 18h      ; shr        ebx, 24

+        db 0ebh

+        db CheckInitFlag - $ - 1      ; jmp CheckInitFlag

+

+; Processor is x2APIC capable, so get 32-bit x2APIC ID

+X2Apic::

+        db 66h,  0B8h

+        dd 0000000Bh                  ; mov        eax, 0b

+        db 66h, 31h, 0c9h             ; xor        ecx, ecx

+        db 0Fh,  0A2h                 ; cpuid

+        db 66h, 89h, 0d3h             ; mov        ebx, edx

+

+CheckInitFlag::

+; EBX is keeping APIC ID

+; If it is the first time AP wakes up, just record AP's BIST

+; Otherwise, switch to flat mode

+

+        db 0BEh

+        dw InitFlag                   ; mov        si,  InitFlag

+        db 66h,  83h, 3Ch, 00h        ; cmp        dword ptr [si], 0

+        db 74h

+        db flat32Start - $ - 1        ; jz         flat32Start

+

+; Increase ApCount as processor number for index of BIST Info array

+

+        db 66h, 0a1h                  ; mov        eax, [ApCountLocation]

+        dw ApCountLocation

+IncApCount::

+        db 66h, 67h, 8dh, 48h, 01     ; lea        ecx, [eax+1]

+        db 0f0h, 66h, 0fh, 0b1h, 0eh  ; lock       cmpxchg [ApCountLocation], ecx

+        dw ApCountLocation

+        db 75h

+        db IncApCount - $ - 1         ; jnz        IncApCount

+

+        db 66h, 0ffh, 0c0h            ; inc        eax                         ; AP processor number starts from 1

+

+; Record BIST information

+;

+        db 66h, 67h, 8dh, 34h, 0c5h   ; lea esi, [BistBuffer + eax*8]

+        dd BistBuffer

+

+        db 66h, 89h, 1ch              ; mov        dword ptr [si], ebx         ; APIC ID

+        db 66h,  89h,  6Ch,  04h      ; mov        dword ptr [si + 4], ebp     ; Store BIST value

+

+        cli

+        hlt

+        jmp $-2

+

+; Switch to flat mode.

+

+flat32Start::

+

+        db 0BEh

+        dw BufferStart                ; mov        si, BufferStart

+        db 66h,  8Bh, 0Ch             ; mov        ecx,dword ptr [si]          ; ECX is keeping the start address of wakeup buffer

+

+        db 0FAh                       ; cli

+        db 0BEh

+        dw GdtrProfile                ; mov        si, GdtrProfile

+        db 66h                        ; db         66h

+        db 2Eh,0Fh, 01h, 14h          ; lgdt       fword ptr cs:[si]

+

+        db 0BEh

+        dw IdtrProfile                ; mov        si, IdtrProfile

+        db 66h                        ; db         66h

+        db 2Eh,0Fh, 01h, 1Ch          ; lidt       fword ptr cs:[si]

+

+        db 33h, 0C0h                  ; xor        ax,  ax

+        db 8Eh, 0D8h                  ; mov        ds,  ax

+        db 0Fh, 20h, 0C0h             ; mov        eax, cr0                    ; Get control register 0

+        db 66h, 83h, 0C8h, 01h        ; or         eax, 000000001h             ; Set PE bit (bit #0)

+        db 0Fh, 22h, 0C0h             ; mov        cr0, eax

+

+

+;step-4:

+

+FLAT32_JUMP::

+        FJMP32  010h,0h               ; Far jmp using code segment descriptor

+

+PMODE_ENTRY::                         ; protected mode entry point

+

+        mov         ax,  8h

+        mov         ds,  ax

+        mov         es,  ax

+        mov         fs,  ax

+        mov         gs,  ax

+        mov         ss,  ax           ; Flat mode setup.

+

+        mov         esi, ecx

+

+        mov         edi, esi

+        add         edi, InitFlag

+        cmp         dword ptr [edi], 2                ; Check whether in S3 boot path

+        jz          ProgramDynamicStack

+

+ProgramStaticStack::

+

+        ;

+        ; Get processor number for this AP

+        ; Note that BSP may become an AP due to SwitchBsp()

+        ;

+

+        xor         ecx, ecx

+        lea         edi, [esi + BistBuffer]

+

+GetProcNumber::

+        cmp         [edi], ebx                       ; APIC ID match?

+        jz          Found

+        add         edi, 8

+        inc         ecx

+        cmp         ecx, dword ptr [esi + ApCountLocation]

+        jbe         GetProcNumber

+

+Found::

+        ;

+        ; ProgramStack

+        ;

+

+        mov         edi, esi

+        add         edi, StackSize

+        mov         eax, dword ptr [edi]

+        inc         ecx

+        mul         ecx                               ; EAX = StackSize * (CpuNumber + 1)

+        dec         ecx

+

+        mov         edi, esi

+        add         edi, StackStart

+        mov         ebx, dword ptr [edi]

+        add         eax, ebx                          ; EAX = StackStart + StackSize * (CpuNumber + 1)

+

+        mov         esp, eax

+        sub         esp, MonitorFilterSize            ; Reserved Monitor data space

+        mov         ebp, ecx                          ; Save processor number in ebp

+        jmp         ProgramStackDone

+

+ProgramDynamicStack::

+

+        mov         edi, esi

+        add         edi, LockLocation

+        mov         al,  NotVacantFlag

+TestLock::

+        xchg        byte ptr [edi], al

+        cmp         al,  NotVacantFlag

+        jz          TestLock

+

+        mov         edi, esi

+        add         edi, StackSize

+        mov         eax, dword ptr [edi]

+        mov         edi, esi

+        add         edi, StackStart

+        add         eax, dword ptr [edi]

+        mov         esp, eax

+        mov         dword ptr [edi], eax

+

+Releaselock::

+        mov         al,  VacantFlag

+        mov         edi, esi

+        add         edi, LockLocation

+        xchg        byte ptr [edi], al

+

+ProgramStackDone::

+

+        ;

+        ; Call assembly function to initialize FPU.

+        ;

+        mov         ebx, InitializeFloatingPointUnits

+        call        ebx

+

+        ;

+        ; Call C Function

+        ;

+        mov         edi, esi

+        add         edi, RendezvousProc

+        add         esi, ApLoopModeLocation              ; esi = ApLoopMode address location

+                                                         

+        xor         ebx, ebx                          

+        mov         dword ptr [esp + 0Ch], ebx           ; Clean ReadyToBoot Flag

+        mov         bx, bp                               ; bx = the lowest 16bit of CpuNumber

+        or          ebx, StartupApSignal                 ; Construct AP run Singal

+

+WakeUpThisAp::

+        mov         eax, dword ptr [edi]

+        test        eax, eax

+        jz          CheckWakeUpManner

+

+        push        ebp                                  ; Push processor number

+        call        eax                                  ; Call C function

+        add         esp, 4

+

+        ;

+        ; Check if BSP was switched

+        ;

+        mov         eax, offset mBspSwitched

+        cmp         byte ptr [eax], 0

+        jz          CheckReadyToBoot

+

+        mov         byte ptr [eax], 0                 ;clear BSP switch flag

+

+        mov         eax, offset mNewProcessorNumber

+        mov         ebp, [eax]                        ; rbp = new processor number

+

+        mov         bx, bp                            ; bx = the lowest 16bit of CpuNumber

+

+        ;

+        ; Assign the dedicated AP stack for the new AP

+        ;

+        mov         eax, offset mMonitorDataAddress

+        mov         esp, [eax]

+

+CheckReadyToBoot::

+        mov         eax, dword ptr [esi]                 ; eax = ApLoopMode for POST

+        cmp         byte ptr [esp + 0Ch], 1                ; Check ReadyToBoot flag?

+        jnz         CheckWakeUpManner

+

+        mov         eax, ApInHltLoop

+        cmp         byte ptr [esp + 0Dh], 1              ; Check if C-State enable?

+        jnz         CheckWakeUpManner

+

+        mov         eax, ApInMwaitLoop                   ; eax = ApLoopMode for Read To Boot

+         

+CheckWakeUpManner::

+        cli

+        cmp         eax, ApInHltLoop

+        jz          HltApLoop

+

+        cmp         eax, ApInMwaitLoop

+        jnz         CheckRunSignal

+

+ApMwaitLoop::

+        mov         eax, esp                      ; Set Monitor Address

+        xor         ecx, ecx                      ; ecx = 0

+        xor         edx, edx                      ; edx = 0

+        DB          0fh, 1, 0c8h                  ; MONITOR

+

+        mov         eax, dword ptr [esp + 4]      ; Mwait Cx, Target C-State per eax[7:4]

+        DB          0fh, 1, 0c9h                  ; MWAIT

+

+CheckRunSignal::

+        cmp         dword ptr [esp], ebx          ; Check if run signal correct?

+        jz          WakeUpThisAp                  ; Jmp to execute AP task

+        PAUSE32

+        jmp         CheckReadyToBoot              ; Unknown break, go checking run manner

+

+HltApLoop::

+        cli

+        hlt

+        jmp         HltApLoop                     ; Jump to halt loop

+

+RendezvousFunnelProc   ENDP

+RendezvousFunnelProcEnd::

+;-------------------------------------------------------------------------------------

+;  AsmGetAddressMap (&AddressMap);

+;-------------------------------------------------------------------------------------

+AsmGetAddressMap   PROC  near C  PUBLIC

+

+        pushad

+        mov         ebp,esp

+

+        mov         ebx, dword ptr [ebp+24h]

+        mov         dword ptr [ebx], RendezvousFunnelProcStart

+        mov         dword ptr [ebx+4h], PMODE_ENTRY - RendezvousFunnelProcStart

+        mov         dword ptr [ebx+8h], FLAT32_JUMP - RendezvousFunnelProcStart

+        mov         dword ptr [ebx+0ch], RendezvousFunnelProcEnd - RendezvousFunnelProcStart

+

+        popad

+        ret

+AsmGetAddressMap   ENDP

+

+;-------------------------------------------------------------------------------------

+;AsmExchangeRole procedure follows. This procedure executed by current BSP, that is

+;about to become an AP. It switches it'stack with the current AP.

+;AsmExchangeRole (IN   CPU_EXCHANGE_INFO    *MyInfo, IN   CPU_EXCHANGE_INFO    *OthersInfo);

+;-------------------------------------------------------------------------------------

+CPU_SWITCH_STATE_IDLE          equ        0

+CPU_SWITCH_STATE_STORED        equ        1

+CPU_SWITCH_STATE_LOADED        equ        2

+

+AsmExchangeRole   PROC  near C  PUBLIC

+        ; DO NOT call other functions in this function, since 2 CPU may use 1 stack

+        ; at the same time. If 1 CPU try to call a functiosn, stack will be corrupted.

+        pushad

+        mov         ebp,esp

+

+        ; esi contains MyInfo pointer

+        mov         esi, dword ptr [ebp+24h]

+

+        ; edi contains OthersInfo pointer

+        mov         edi, dword ptr [ebp+28h]

+

+        ;Store EFLAGS, GDTR and IDTR regiter to stack

+        pushfd

+        sgdt        fword ptr [esi+8]

+        sidt        fword ptr [esi+14]

+

+        ; Store the its StackPointer

+        mov         dword ptr [esi+4],esp

+

+        ; update its switch state to STORED

+        mov         byte ptr [esi], CPU_SWITCH_STATE_STORED

+

+WaitForOtherStored::

+        ; wait until the other CPU finish storing its state

+        cmp         byte ptr [edi], CPU_SWITCH_STATE_STORED

+        jz          OtherStored

+        pause

+        jmp         WaitForOtherStored

+

+OtherStored::

+        ; Since another CPU already stored its state, load them

+        ; load GDTR value

+        lgdt        fword ptr [edi+8]

+

+        ; load IDTR value

+        lidt        fword ptr [edi+14]

+

+        ; load its future StackPointer

+        mov         esp, dword ptr [edi+4]

+

+        ; update the other CPU's switch state to LOADED

+        mov         byte ptr [edi], CPU_SWITCH_STATE_LOADED

+

+WaitForOtherLoaded::

+        ; wait until the other CPU finish loading new state,

+        ; otherwise the data in stack may corrupt

+        cmp         byte ptr [esi], CPU_SWITCH_STATE_LOADED

+        jz          OtherLoaded

+        pause

+        jmp         WaitForOtherLoaded

+

+OtherLoaded::

+        ; since the other CPU already get the data it want, leave this procedure

+        popfd

+

+        popad

+        ret

+AsmExchangeRole   ENDP

+END

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.c b/IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.c
new file mode 100644
index 0000000..835b422
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.c
@@ -0,0 +1,149 @@
+/** @file

+

+  Code for Max CPUID Limit Feature

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  LimitCpuIdValue.c

+

+**/

+

+#include "LimitCpuIdValue.h"

+

+BOOLEAN    EnableLimitCpuIdValue[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];

+

+/**

+  Detect capability of Max CPUID Limit feature for specified processor.

+  

+  This function detects capability of Max CPUID Limit feature for specified processor.

+

+  @param  ProcessorNumber   The handle number of specified processor.

+

+**/

+VOID

+MaxCpuidLimitDetect (

+  UINTN   ProcessorNumber

+  )

+{

+  EFI_CPUID_REGISTER  *CpuidRegisters;

+  UINT8               MaxCpuid;

+

+  CpuidRegisters   = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_SIGNATURE);

+  ASSERT (CpuidRegisters != NULL);

+

+  MaxCpuid         = (UINT8) CpuidRegisters->RegEax;

+  if (MaxCpuid > 3) {

+    SetProcessorFeatureCapability (ProcessorNumber, MaxCpuidValueLimit, NULL);

+  }

+}

+

+/**

+  Configures Processor Feature Lists for Max CPUID Limit feature for all processors.

+  

+  This function configures Processor Feature Lists for Max CPUID Limit feature for all processors.

+

+**/

+VOID

+MaxCpuidLimitConfigFeatureList (

+  VOID

+  )

+{

+  UINTN                 ProcessorNumber;

+  BOOLEAN               UserConfigurationSet;

+

+  UserConfigurationSet = FALSE;

+  if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_MAX_CPUID_VALUE_LIMIT_BIT) != 0) {

+    UserConfigurationSet = TRUE;

+  }

+

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+    //

+    // Check whether this logical processor supports Max CPUID Value Limit

+    //

+    if (GetProcessorFeatureCapability (ProcessorNumber, MaxCpuidValueLimit, NULL)) {

+      if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {

+        //

+        // Set the bit of Max CPUID Value Limit capability according to BSP capability.

+        //

+        PcdSet32 (PcdCpuProcessorFeatureCapability, PcdGet32 (PcdCpuProcessorFeatureCapability) | PCD_CPU_MAX_CPUID_VALUE_LIMIT_BIT);

+        //

+        // Set the bit of Max CPUID Value Limit setting according to BSP setting.

+        //

+        if (UserConfigurationSet) {

+          PcdSet32 (PcdCpuProcessorFeatureSetting, PcdGet32 (PcdCpuProcessorFeatureSetting) | PCD_CPU_MAX_CPUID_VALUE_LIMIT_BIT);

+        }

+      }

+

+      //

+      // If this logical processor supports Max CPUID Value Limit, then add feature into feature list for operation

+      // on corresponding register.

+      //

+      EnableLimitCpuIdValue[ProcessorNumber] = UserConfigurationSet;

+      AppendProcessorFeatureIntoList (ProcessorNumber, MaxCpuidValueLimit, &(EnableLimitCpuIdValue[ProcessorNumber]));

+    }

+  }

+}

+

+/**

+  Produces entry of Max CPUID Limit feature in Register Table for specified processor.

+  

+  This function produces entry of Max CPUID Limit feature in Register Table for specified processor.

+

+  @param  ProcessorNumber   The handle number of specified processor.

+  @param  Attribute         Pointer to the attribute

+

+**/

+VOID

+MaxCpuidLimitReg (

+  UINTN      ProcessorNumber,

+  VOID       *Attribute

+  )

+{

+  BOOLEAN    *Enable;

+  UINT64     Value;

+

+  //

+  // If Attribute is TRUE, then write 1 to MSR_IA32_MISC_ENABLE[22].

+  // Otherwise, write 0 to the bit.

+  //

+  Enable = (BOOLEAN *) Attribute;

+  Value  = 0;

+  if (*Enable) {

+    Value = 1;

+  }

+

+  WriteRegisterTable (

+    ProcessorNumber,

+    Msr,

+    MSR_IA32_MISC_ENABLE,

+    N_MSR_LIMIT_CPUID_MAXVAL,

+    1,

+    Value

+    );

+}

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.h b/IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.h
new file mode 100644
index 0000000..e948094
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/LimitCpuIdValue.h
@@ -0,0 +1,82 @@
+/** @file

+

+  Include file for Max CPUID Limit Feature

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  LimitCpuIdValue.h

+

+**/

+

+#ifndef _CPU_LIMIT_CPUID_VALUE_H_

+#define _CPU_LIMIT_CPUID_VALUE_H_

+

+#include "Cpu.h"

+#include "MpService.h"

+

+/**

+  Detect capability of Max CPUID Limit feature for specified processor.

+  

+  This function detects capability of Max CPUID Limit feature for specified processor.

+

+  @param  ProcessorNumber   The handle number of specified processor.

+

+**/

+VOID

+MaxCpuidLimitDetect (

+  UINTN   ProcessorNumber

+  );

+

+/**

+  Configures Processor Feature Lists for Max CPUID Limit feature for all processors.

+  

+  This function configures Processor Feature Lists for Max CPUID Limit feature for all processors.

+

+**/

+VOID

+MaxCpuidLimitConfigFeatureList (

+  VOID

+  );

+

+/**

+  Produces entry of Max CPUID Limit feature in Register Table for specified processor.

+  

+  This function produces entry of Max CPUID Limit feature in Register Table for specified processor.

+

+  @param  ProcessorNumber   The handle number of specified processor.

+  @param  Attribute         Pointer to the attribute

+

+**/

+VOID

+MaxCpuidLimitReg (

+  UINTN      ProcessorNumber,

+  VOID       *Attribute

+  );

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.c b/IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.c
new file mode 100644
index 0000000..a02c82d
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.c
@@ -0,0 +1,162 @@
+/** @file

+

+  Code for APIC feature.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  MpApic.c

+

+**/

+

+#include "MpApic.h"

+

+/**

+  Sort the APIC ID of all processors.

+

+  This function sorts the APIC ID of all processors so that processor number is assigned in the

+  ascending order of APIC ID which eases MP debugging. SMBIOS logic also depends on this assumption.

+

+**/

+VOID

+SortApicId (

+  VOID

+  )

+{

+  UINTN   Index1;

+  UINTN   Index2;

+  UINTN   Index3;

+  UINT32  ApicId;

+  UINT32  Bist;

+

+  if (mExchangeInfo->ApCount != 0) {

+    mCpuConfigConextBuffer.NumberOfProcessors += mExchangeInfo->ApCount;

+

+    for (Index1 = 0; Index1 < mExchangeInfo->ApCount; Index1++) {

+      Index3 = Index1;

+      //

+      // Sort key is the hardware default APIC ID

+      //

+      ApicId = mExchangeInfo->BistBuffer[Index1].ApicId;

+      for (Index2 = Index1 + 1; Index2 <= mExchangeInfo->ApCount; Index2++) {

+        if (ApicId > mExchangeInfo->BistBuffer[Index2].ApicId) {

+          Index3 = Index2;

+          ApicId = mExchangeInfo->BistBuffer[Index2].ApicId;

+        }

+      }

+      if (Index3 != Index1) {

+        mExchangeInfo->BistBuffer[Index3].ApicId = mExchangeInfo->BistBuffer[Index1].ApicId;

+        mExchangeInfo->BistBuffer[Index1].ApicId = ApicId;

+        Bist = mExchangeInfo->BistBuffer[Index3].Bist;

+        mExchangeInfo->BistBuffer[Index3].Bist = mExchangeInfo->BistBuffer[Index1].Bist;

+        mExchangeInfo->BistBuffer[Index1].Bist = Bist;

+      }

+    }

+

+    //

+    // Get the processor number for the BSP

+    //

+    ApicId = GetInitialApicId ();

+    for (Index1 = 0; Index1 < mCpuConfigConextBuffer.NumberOfProcessors; Index1++) {

+      if (mExchangeInfo->BistBuffer[Index1].ApicId == ApicId) {

+        mCpuConfigConextBuffer.BspNumber = Index1;

+        break;

+      }

+    }

+  }

+}

+

+/**

+  Check if there is legacy APIC ID conflict among all processors.

+

+  @retval EFI_SUCCESS      No coflict

+  @retval EFI_UNSUPPORTED  There is legacy APIC ID conflict and can't be rsolved in xAPIC mode

+**/

+EFI_STATUS

+CheckApicId (

+  VOID

+  )

+{

+  UINTN               Index1;

+  UINTN               Index2;

+  BOOLEAN             X2ApicCapable;

+

+  X2ApicCapable = FALSE;

+

+  //

+  // If xAPIC mode is configured, then check if there is any APIC ID conflict.

+  //

+  ASSERT (mCpuConfigConextBuffer.NumberOfProcessors <= FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber));

+

+  if (mCpuConfigConextBuffer.NumberOfProcessors > 255) {

+    DEBUG ((EFI_D_ERROR, "Number of processors > 255!\n"));

+    return EFI_UNSUPPORTED;

+  } else {

+    //

+    // Check if there is 8-bit legacy APIC ID conflict with hardware default socket IDs.

+    //

+    for (Index1 = 0; Index1 < mCpuConfigConextBuffer.NumberOfProcessors; Index1++) {

+     for (Index2 = Index1 + 1; Index2 < mCpuConfigConextBuffer.NumberOfProcessors; Index2++) {

+       if ((UINT8) mExchangeInfo->BistBuffer[Index1].ApicId == (UINT8) mExchangeInfo->BistBuffer[Index2].ApicId) {

+          break;

+        }

+      }

+      if (Index2 < mCpuConfigConextBuffer.NumberOfProcessors) {

+        DEBUG ((EFI_D_ERROR, "Legacy APIC ID conflict with hardware socket ID but x2APIC mode is not supported!\n"));

+        return EFI_UNSUPPORTED;

+      }

+    }

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Assign a package scope BSP responsible for package scope programming.

+

+  This functions assigns the processor with the least APIC ID within a processor package as

+  the package BSP.

+

+**/

+VOID

+AssignPackageBsp (

+  VOID

+  )

+{

+  UINTN  Index;

+  UINT32 PackageId;

+

+  mCpuConfigConextBuffer.CollectedDataBuffer[0].PackageBsp = TRUE;

+  PackageId = mCpuConfigConextBuffer.CollectedDataBuffer[0].ProcessorLocation.Package;

+  for (Index = 1; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) {

+    if (PackageId != mCpuConfigConextBuffer.CollectedDataBuffer[Index].ProcessorLocation.Package) {

+      PackageId = mCpuConfigConextBuffer.CollectedDataBuffer[Index].ProcessorLocation.Package;

+      mCpuConfigConextBuffer.CollectedDataBuffer[Index].PackageBsp = TRUE;

+    }

+  }

+}

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.h b/IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.h
new file mode 100644
index 0000000..e4f05ca
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/MpApic.h
@@ -0,0 +1,77 @@
+/** @file

+

+  Include file for APIC feature.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  MpApic.h

+

+**/

+

+#ifndef _CPU_MP_APIC_H_

+#define _CPU_MP_APIC_H_

+

+#include "Cpu.h"

+

+/**

+  Sort the APIC ID of all processors.

+

+  This function sorts the APIC ID of all processors so that processor number is assigned in the

+  ascending order of APIC ID which eases MP debugging. SMBIOS logic also depends on this assumption.

+

+**/

+VOID

+SortApicId (

+  VOID

+  );

+

+/**

+  Check if there is legacy APIC ID conflict among all processors.

+

+  @retval EFI_SUCCESS      No coflict or conflict was resoved by force x2APIC mode

+  @retval EFI_UNSUPPORTED  There is legacy APIC ID conflict and can't be rsolved in xAPIC mode

+**/

+EFI_STATUS

+CheckApicId (

+  VOID

+  );

+

+/**

+  Assign a package scope BSP responsible for package scope programming.

+

+  This functions assigns the processor with the least APIC ID within a processor package as

+  the package BSP.

+

+**/

+VOID

+AssignPackageBsp (

+  VOID

+  );

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.c b/IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.c
new file mode 100644
index 0000000..d13082f
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.c
@@ -0,0 +1,578 @@
+/** @file

+

+  Common functions for CPU DXE module.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  MpCommon.c

+

+**/

+

+#include "MpService.h"

+#include "Cpu.h"

+#include "ArchSpecificDef.h"

+

+AP_PROCEDURE          mApFunction = NULL;

+AP_PROCEDURE          SimpleAPProcedure;

+UINT32                NumberToFinish;

+UINTN                 mApCount = 0;

+UINTN                 mStartupVectorSize;

+EFI_PHYSICAL_ADDRESS  mApMachineCheckHandlerBase;

+UINT32                mApMachineCheckHandlerSize;

+

+/**

+  Allocates startup vector for APs.

+

+  This function allocates Startup vector for APs.

+

+  @param  Size  The size of startup vector.

+

+**/

+VOID

+AllocateStartupVector (

+  UINTN   Size

+  )

+{

+  EFI_STATUS                            Status;

+  EFI_GENERIC_MEMORY_TEST_PROTOCOL      *GenMemoryTest;

+  EFI_PHYSICAL_ADDRESS                  StartAddress;

+

+  mStartupVectorSize = Size;

+

+  //

+  // In order to allocate startup vector for APs under 1M, try to locate

+  // Generic Memory Test Protocol to test memory before allocation.

+  //

+  Status = gBS->LocateProtocol (

+                  &gEfiGenericMemTestProtocolGuid,

+                  NULL,

+                  (VOID **) &GenMemoryTest

+                  );

+  if (EFI_ERROR (Status)) {

+    GenMemoryTest = NULL;

+  }

+

+  //

+  // Allocate wakeup buffer below 640K. Don't touch legacy region.

+  // Leave some room immediately below 640K in for CSM module.

+  // PcdEbdaReservedMemorySize has been required to be a multiple of 4KB.

+  //

+  StartAddress = 0xA0000 - PcdGet32 (PcdEbdaReservedMemorySize) - (EFI_SIZE_TO_PAGES (Size) * EFI_PAGE_SIZE);

+  for (mStartupVector = StartAddress; mStartupVector >= 0x2000; mStartupVector -= (EFI_SIZE_TO_PAGES (Size) * EFI_PAGE_SIZE)) {

+    //

+    // If Generic Memory Test Protocol has been located successfully, call CompatibleRangeTest() to test

+    // the range we are going to allocate. If the protocol has not been located, then the memory test would

+    // be skipped.

+    //

+    if (GenMemoryTest != NULL) {

+      Status = GenMemoryTest->CompatibleRangeTest (

+                                GenMemoryTest,

+                                mStartupVector,

+                                EFI_SIZE_TO_PAGES (Size) * EFI_PAGE_SIZE

+                                );

+      if (EFI_ERROR (Status)) {

+        continue;

+      }

+    }

+

+    //

+    // If finally no CSM in the platform, this wakeup buffer is to be used in S3 boot path.

+    //

+    Status = gBS->AllocatePages (

+                    AllocateAddress,

+                    EfiReservedMemoryType,

+                    EFI_SIZE_TO_PAGES (Size),

+                    &mStartupVector

+                    );

+

+    if (!EFI_ERROR (Status)) {

+      break;

+    }

+  }

+

+  ASSERT_EFI_ERROR (Status);

+}

+

+ /**

+  Count the number of APs that have been switched

+  to E0000 or F0000 segments by ReAllocateMemoryForAP().

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+LegacyRegionAPCount (

+  IN UINTN  ProcessorNumber

+  )

+{

+  AcquireSpinLock (&mMPSystemData.APSerializeLock);

+

+  mApCount++;

+

+  ReleaseSpinLock (&mMPSystemData.APSerializeLock);

+}

+

+

+/**

+  This AP function will place AP to the suitable state.

+  

+  If C-State is enable, try to place AP to the Mwait-Loop with deepest C-State, 

+  otherwize place AP to  Hlt-Loop state.

+

+  @param  Buffer  Pointer to MP Services.

+**/

+VOID

+EFIAPI

+ChangeApLoopMode (

+  IN  VOID     *Buffer

+  ) 

+{

+  UINTN                      ProcessorNumber;

+  MONITOR_MWAIT_DATA         *MonitorAddr;

+

+  WhoAmI (&mMpService, &ProcessorNumber);

+

+  //

+  // Set the ReadyToBootFlag for AP.

+  //

+  MonitorAddr = GetMonitorDataAddress (ProcessorNumber);

+  MonitorAddr->ReadyToBootFlag = TRUE;

+}

+

+/**

+  Protocol notification that will wake up and place AP to the suitable state

+  before booting to OS.

+

+  @param  Event                 The triggered event.

+  @param  Context               Context for this event.

+**/

+VOID

+EFIAPI

+ChangeApLoopModeCallBack (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  )

+{

+  EFI_STATUS                 Status;

+

+  while (ApRunning()) {

+    CpuPause ();

+  }

+ 

+  Status = mMpService.StartupAllAPs (

+                        &mMpService,

+                        ChangeApLoopMode,

+                        FALSE,

+                        NULL,

+                        0,

+                        NULL,

+                        NULL

+                        );

+  ASSERT_EFI_ERROR (Status);

+}

+

+/**

+  Protocol notification that is fired when LegacyBios protocol is installed.

+

+  Re-allocate a wakeup buffer from E/F segment because the previous wakeup buffer

+  under 640K won't be preserved by the legacy OS.

+

+  @param  Event                 The triggered event.

+  @param  Context               Context for this event.

+**/

+VOID

+EFIAPI

+ReAllocateMemoryForAP (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  )

+{

+  EFI_LEGACY_BIOS_PROTOCOL   *LegacyBios;

+  VOID                       *LegacyRegion;

+  EFI_STATUS                 Status;

+  MP_CPU_EXCHANGE_INFO       *ExchangeInfo;

+  MP_ASSEMBLY_ADDRESS_MAP    AddressMap;

+

+  Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, (VOID **)&LegacyBios);

+  if (EFI_ERROR (Status)) {

+    return ;

+  }

+

+  //

+  // Wait for all APs to finish their task before switching wakeup buffer

+  //

+  while (ApRunning()) {

+    CpuPause ();

+  }

+

+  //

+  // Allocate 4K aligned bytes from either 0xE0000 or 0xF0000.

+  // Note some CSM16 does not satisfy alignment request, so allocate a buffer of 2*4K

+  // and adjust the base address myself.

+  //

+  Status = LegacyBios->GetLegacyRegion (

+                         LegacyBios,

+                         0x2000,

+                         0,

+                         0x1000,

+                         &LegacyRegion

+                         );

+  ASSERT_EFI_ERROR (Status);

+

+  if ((((UINTN)LegacyRegion) & 0xfff) != 0) {

+    LegacyRegion = (VOID *)(UINTN)((((UINTN)LegacyRegion) + 0xfff) & ~((UINTN)0xfff));

+  }

+

+  //

+  // Get the address map of startup code for AP,

+  // including code size, and offset of long jump instructions to redirect.

+  //

+  AsmGetAddressMap (&AddressMap);

+

+  //

+  // Update exchange info and copy AP startup code to new buffer in legacy region.

+  //

+  ExchangeInfo              = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mStartupVector + AddressMap.Size);

+  ExchangeInfo->BufferStart = (UINT32) (UINTN) LegacyRegion;

+  RedirectFarJump (&AddressMap, (EFI_PHYSICAL_ADDRESS) (UINTN) LegacyRegion);

+

+  //

+  // Switch all APs to use new wakeup buffer

+  //

+  Status = LegacyBios->CopyLegacyRegion (

+                         LegacyBios,

+                         mStartupVectorSize,

+                         LegacyRegion,

+                         (VOID *)(UINTN)mStartupVector

+                         );

+

+  SendInitSipiSipiIpis (

+    TRUE,

+    0,

+    LegacyRegionAPCount

+    );

+

+  //

+  // Wait until all APs finish

+  //

+  while (mApCount < mAcpiCpuData->NumberOfCpus - 1) {

+    CpuPause ();

+  }

+

+  //

+  // Free original wakeup buffer

+  //

+  FreePages ((VOID *)(UINTN)mStartupVector, EFI_SIZE_TO_PAGES (mStartupVectorSize));

+

+  mStartupVector = (EFI_PHYSICAL_ADDRESS)(UINTN)LegacyRegion;

+  mAcpiCpuData->StartupVector = mStartupVector;

+  mExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (mStartupVector + AddressMap.Size);

+}

+

+/**

+  Allocate aligned ACPI NVS memory below 4G.

+

+  This function allocates aligned ACPI NVS memory below 4G.

+

+  @param  Size       Size of memory region to allocate

+  @param  Alignment  Alignment in bytes

+

+  @return Base address of the allocated region

+

+**/

+VOID*

+AllocateAlignedAcpiNvsMemory (

+  IN  UINTN         Size,

+  IN  UINTN         Alignment

+  )

+{

+  UINTN       PointerValue;

+  VOID        *Pointer;

+

+  Pointer = AllocateAcpiNvsMemoryBelow4G (Size + Alignment - 1);

+

+  PointerValue  = (UINTN) Pointer;

+  PointerValue  = (PointerValue + Alignment - 1) / Alignment * Alignment;

+

+  Pointer      = (VOID *) PointerValue;

+

+  return Pointer;

+}

+

+/**

+  Allocate EfiACPIMemoryNVS below 4G memory address.

+

+  This function allocates EfiACPIMemoryNVS below 4G memory address.

+

+  @param  Size         Size of memory to allocate.

+

+  @return Allocated address for output.

+

+**/

+VOID*

+AllocateAcpiNvsMemoryBelow4G (

+  IN   UINTN   Size

+  )

+{

+  UINTN                 Pages;

+  EFI_PHYSICAL_ADDRESS  Address;

+  EFI_STATUS            Status;

+  VOID*                 Buffer;

+

+  Pages = EFI_SIZE_TO_PAGES (Size);

+  Address = 0xffffffff;

+

+  Status  = gBS->AllocatePages (

+                   AllocateMaxAddress,

+                   EfiACPIMemoryNVS,

+                   Pages,

+                   &Address

+                   );

+  ASSERT_EFI_ERROR (Status);

+

+  Buffer = (VOID *) (UINTN) Address;

+  ZeroMem (Buffer, Size);

+

+  return Buffer;

+}

+

+/**

+  Sends INIT-SIPI-SIPI to AP.

+

+  This function sends INIT-SIPI-SIPI to AP, and assign procedure specified by ApFunction.

+

+  @param  Broadcast   If TRUE, broadcase IPI to all APs; otherwise, send to specified AP.

+  @param  ApicID      The Local APIC ID of the specified AP. If Broadcast is TRUE, it is ignored.

+  @param  ApFunction  The procedure for AP to work on.

+

+**/

+VOID

+SendInitSipiSipiIpis (

+  IN BOOLEAN            Broadcast,

+  IN UINT32             ApicID,

+  IN AP_PROCEDURE       ApFunction

+  )

+{

+  mApFunction = ApFunction;

+

+  if (Broadcast) {

+    SendInitSipiSipiAllExcludingSelf ((UINT32) mStartupVector);

+  } else {

+    SendInitSipiSipi (ApicID, (UINT32) mStartupVector);

+  }

+}

+

+/**

+  A simple wrapper function dispatched to AP.

+

+  This function is a simple wrapper function dispatched to AP. It invokes task for AP, and count down

+  the number.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+SimpleApProcWrapper (

+  IN UINTN  ProcessorNumber

+  )

+{

+  //

+  // Program virtual wire mode and Local APIC timer for AP, since it will be lost after AP wake up

+  //

+  ProgramVirtualWireMode ();

+  DisableLvtInterrupts ();

+  InitializeApicTimer (mLocalApicTimerDivisor, mLocalApicTimerInitialCount, FALSE, 0);

+

+  // Initialize Debug Agent to support source level debug on AP code.

+  //

+  InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_AP, NULL, NULL);

+

+  //

+  // If it is necessary to restore register setting after INIT signal,

+  // call SetProcessorRegister().

+  //

+  if (mRestoreSettingAfterInit) {

+    SetProcessorRegister (ProcessorNumber);

+  }

+

+  //

+  // Invoke task for AP.

+  //

+  SimpleAPProcedure (ProcessorNumber);

+

+  //

+  // Count down the number with lock mechanism.

+  //

+  InterlockedDecrement (&NumberToFinish);

+}

+

+/**

+  Dispatches task to AP.

+

+  This function dispatches task to AP. The BSP waits until specified APs have finished.

+

+  @param  Broadcast   If TRUE, send task to all APs; otherwise, send to specified AP.

+  @param  ApicID      The Local APIC ID of the specified AP. If Broadcast is TRUE, it is ignored.

+  @param  Procedure   The procedure for AP to work on.

+

+**/

+VOID

+DispatchAPAndWait (

+  IN BOOLEAN             Broadcast,

+  IN UINT32              ApicID,

+  IN AP_PROCEDURE        Procedure

+  )

+{

+  //

+  // Prepares the task for AP. It will invoked by SimpleApProcWrapper.

+  //

+  SimpleAPProcedure = Procedure;

+

+  //

+  // Checks whether the function is for broadcast.

+  //

+  if (Broadcast) {

+    //

+    // If in broadcast mode, the number to finish is the number of all APs

+    //

+    NumberToFinish = (UINT32) mCpuConfigConextBuffer.NumberOfProcessors - 1;

+  } else {

+    //

+    // If in non-broadcast mode, the number to finish is 1

+    //

+    NumberToFinish = 1;

+  }

+

+  //

+  // Wake up specified AP(s), and make them work on SimpleApProcWrapper, which

+  // will in turn invoke Procedure.

+  //

+  SendInitSipiSipiIpis (

+    Broadcast,

+    ApicID,

+    SimpleApProcWrapper

+    );

+

+  //

+  // BSP waits until specified AP(s) have finished.

+  //

+  while (NumberToFinish > 0) {

+    CpuPause ();

+  }

+}

+

+/**

+  Creates a copy of GDT and IDT for all APs.

+

+  This function creates a copy of GDT and IDT for all APs.

+

+  @param  Gdtr   Base and limit of GDT for AP

+  @param  Idtr   Base and limit of IDT for AP

+

+**/

+VOID

+PrepareGdtIdtForAP (

+  OUT IA32_DESCRIPTOR          *Gdtr,

+  OUT IA32_DESCRIPTOR          *Idtr

+  )

+{

+  SEGMENT_DESCRIPTOR        *GdtForAP;

+  INTERRUPT_GATE_DESCRIPTOR *IdtForAP;

+  IA32_DESCRIPTOR           GdtrForBSP;

+  IA32_DESCRIPTOR           IdtrForBSP;

+  VOID                      *MachineCheckHandlerBuffer;

+

+  //

+  // Get the BSP's data of GDT and IDT

+  //

+  AsmReadGdtr ((IA32_DESCRIPTOR *) &GdtrForBSP);

+  AsmReadIdtr ((IA32_DESCRIPTOR *) &IdtrForBSP);

+

+  //

+  // Allocate ACPI NVS memory for GDT, IDT, and machine check handler.

+  // Combine allocation for ACPI NVS memory under 4G to save memory.

+  //

+  GdtForAP = AllocateAlignedAcpiNvsMemory (

+               (GdtrForBSP.Limit + 1) + (IdtrForBSP.Limit + 1) + (UINTN) ApMachineCheckHandlerEnd - (UINTN) ApMachineCheckHandler,

+               8

+               );

+

+  //

+  // GDT base is 8-bype aligned, and its size is multiple of 8-bype, so IDT base here is

+  // also 8-bype aligned.

+  //

+  IdtForAP = (INTERRUPT_GATE_DESCRIPTOR *) ((UINTN) GdtForAP + GdtrForBSP.Limit + 1);

+  MachineCheckHandlerBuffer = (VOID *) ((UINTN) GdtForAP + (GdtrForBSP.Limit + 1) + (IdtrForBSP.Limit + 1));

+  //

+  // Make copy for APs' GDT & IDT

+  //

+  CopyMem (GdtForAP, (VOID *) GdtrForBSP.Base, GdtrForBSP.Limit + 1);

+  CopyMem (IdtForAP, (VOID *) IdtrForBSP.Base, IdtrForBSP.Limit + 1);

+

+  //

+  // Copy code for AP's machine check handler to ACPI NVS memory, and register in IDT

+  //

+  CopyMem (

+    MachineCheckHandlerBuffer,

+    (VOID *) (UINTN) ApMachineCheckHandler,

+    (UINTN) ApMachineCheckHandlerEnd - (UINTN) ApMachineCheckHandler

+    );

+  SetIdtEntry ((UINTN) MachineCheckHandlerBuffer, &IdtForAP[INTERRUPT_HANDLER_MACHINE_CHECK]);

+

+  //

+  // Set AP's profile for GDTR and IDTR

+  //

+  Gdtr->Base  = (UINTN) GdtForAP;

+  Gdtr->Limit = GdtrForBSP.Limit;

+

+  Idtr->Base  = (UINTN) IdtForAP;

+  Idtr->Limit = IdtrForBSP.Limit;

+

+  //

+  // Save the AP's machine check handler information

+  //

+  mApMachineCheckHandlerBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MachineCheckHandlerBuffer;

+  mApMachineCheckHandlerSize = (UINT32) ((UINTN) ApMachineCheckHandlerEnd - (UINTN) ApMachineCheckHandler);

+}

+

+/**

+  Get mointor data address for specified processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+  @return Pointer to monitor data.

+**/

+MONITOR_MWAIT_DATA *

+EFIAPI

+GetMonitorDataAddress (

+  IN UINTN  ProcessorNumber

+  )

+{

+  return (MONITOR_MWAIT_DATA *) ((UINT8*) mExchangeInfo->StackStart + (ProcessorNumber + 1) *  mExchangeInfo->StackSize - MONITOR_FILTER_SIZE);

+}

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.h b/IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.h
new file mode 100644
index 0000000..e873ca0
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/MpCommon.h
@@ -0,0 +1,367 @@
+/** @file

+

+  Include files of common functions for CPU DXE module.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  MpCommon.h

+

+**/

+

+#ifndef _MP_COMMON_H_

+#define _MP_COMMON_H_

+

+#include "ArchSpecificDef.h"

+#include <AcpiCpuData.h>

+#include <IndustryStandard/SmBios.h>

+

+#include <Protocol/Smbios.h>

+#include <Protocol/MpService.h>

+#include <Protocol/LegacyBios.h>

+#include <Protocol/GenericMemoryTest.h>

+#include <Protocol/Cpu.h>

+#include <Protocol/SmmConfiguration.h>

+#include <Protocol/Timer.h>

+#include <Protocol/TcgService.h>

+

+#include <Guid/StatusCodeDataTypeId.h>

+#include <Guid/HtBistHob.h>

+#include <Guid/EventGroup.h>

+#include <Guid/IdleLoopEvent.h>

+

+#include <Library/BaseLib.h>

+#include <Library/SynchronizationLib.h>

+#include <Library/DebugLib.h>

+#include <Library/UefiLib.h>

+#include <Library/HobLib.h>

+#include <Library/HiiLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/ReportStatusCodeLib.h>

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiRuntimeServicesTableLib.h>

+#include <Library/PcdLib.h>

+#include <Library/IoLib.h>

+#include <Library/CpuConfigLib.h>

+#include <Library/CpuLib.h>

+#include <Library/DxeServicesTableLib.h>

+#include <Library/TimerLib.h>

+#include <Library/CpuOnlyResetLib.h>

+#include <Library/UefiCpuLib.h>

+#include <Library/MtrrLib.h>

+#include <Library/SocketLga775Lib.h>

+#include <Library/DebugAgentLib.h>

+#include <Library/LocalApicLib.h>

+#include <Library/PrintLib.h>

+

+#define INTERRUPT_HANDLER_MACHINE_CHECK       0x12

+

+#define VACANT_FLAG           0x00

+#define NOT_VACANT_FLAG       0xff

+

+#define MICROSECOND         10

+

+#pragma pack(1)

+

+typedef  struct {

+  UINT16  LimitLow;

+  UINT16  BaseLow;

+  UINT8   BaseMiddle;

+  UINT8   Attributes1;

+  UINT8	  Attributes2;	

+  UINT8   BaseHigh;

+} SEGMENT_DESCRIPTOR;

+

+#pragma pack()

+

+#define STARTUP_AP_SIGNAL        0x6E750000

+

+typedef enum {

+  ApInHltLoop   = 1,

+  ApInMwaitLoop = 2,

+  ApInRunLoop   = 3

+} AP_LOOP_MODE;

+

+typedef struct {

+  UINT32                    StartupApSignal;

+  UINT32                    MwaitTargetCstate;

+  AP_LOOP_MODE              ApLoopMode;

+  BOOLEAN                   ReadyToBootFlag;

+  BOOLEAN                   CStateEnable;

+} MONITOR_MWAIT_DATA;

+

+//

+// The MONITOR_FILTER_SIZE be mulitple of 16 bytes,

+// to make sure AP's stack is 16-byte alignment on x64 arch.

+//

+#define MONITOR_FILTER_SIZE      sizeof(MONITOR_MWAIT_DATA)

+

+typedef struct {

+  UINT32                    ApicId;

+  UINT32                    Bist;

+} BIST_INFO;

+

+//

+// MTRR table definitions

+//

+typedef struct {

+  UINT16  Index;

+  UINT64  Value;

+} EFI_MTRR_VALUES;

+

+typedef

+VOID

+(EFIAPI *AP_PROC_ENTRY) (

+  IN UINTN  ProcessorNumber

+  );

+

+typedef

+VOID

+(*AP_PROCEDURE) (

+  IN UINTN  ProcessorNumber

+  );

+

+//

+// Note that this structure is located immediately after the AP startup code

+// in the wakeup buffer. this structure is not always writeable if the wakeup

+// buffer is in the legacy region.

+//

+typedef struct {

+  UINTN             Lock;

+  VOID              *StackStart;

+  UINTN             StackSize;

+  AP_PROC_ENTRY     ApFunction;

+  IA32_DESCRIPTOR   GdtrProfile;

+  IA32_DESCRIPTOR   IdtrProfile;

+  UINT32            BufferStart;

+  UINT32            Cr3;

+  UINT32            InitFlag;

+  UINT32            ApCount;

+  AP_LOOP_MODE      ApLoopMode;

+  BIST_INFO         BistBuffer[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];

+} MP_CPU_EXCHANGE_INFO;

+

+extern MP_CPU_EXCHANGE_INFO        *mExchangeInfo;

+extern AP_PROCEDURE                mApFunction;

+extern CPU_CONFIG_CONTEXT_BUFFER   mCpuConfigConextBuffer;

+extern EFI_PHYSICAL_ADDRESS        mApMachineCheckHandlerBase;

+extern UINT32                      mApMachineCheckHandlerSize;

+extern UINTN                       mLocalApicTimerDivisor;

+extern UINT32                      mLocalApicTimerInitialCount;

+

+/**

+  Allocates startup vector for APs.

+

+  This function allocates Startup vector for APs.

+

+  @param  Size  The size of startup vector.

+

+**/

+VOID

+AllocateStartupVector (

+  UINTN   Size

+  );

+

+/**

+  Creates a copy of GDT and IDT for all APs.

+

+  This function creates a copy of GDT and IDT for all APs.

+

+  @param  Gdtr   Base and limit of GDT for AP

+  @param  Idtr   Base and limit of IDT for AP

+

+**/

+VOID

+PrepareGdtIdtForAP (

+  OUT IA32_DESCRIPTOR  *Gdtr,

+  OUT IA32_DESCRIPTOR  *Idtr

+  );

+

+/**

+  Allocate aligned ACPI NVS memory below 4G.

+  

+  This function allocates aligned ACPI NVS memory below 4G.

+

+  @param  Size       Size of memory region to allocate

+  @param  Alignment  Alignment in bytes

+  

+  @return Base address of the allocated region

+

+**/

+VOID*

+AllocateAlignedAcpiNvsMemory (

+  IN  UINTN         Size,

+  IN  UINTN         Alignment

+  );

+

+/**

+  Prepares Startup Vector for APs.

+

+  This function prepares Startup Vector for APs.

+

+**/

+VOID

+PrepareAPStartupVector (

+  VOID

+  );

+

+/**

+  Sets specified IDT entry with given function pointer.

+

+  This function sets specified IDT entry with given function pointer.

+

+  @param  FunctionPointer  Function pointer for IDT entry.

+  @param  IdtEntry         The IDT entry to update.

+

+  @return The original IDT entry value.

+

+**/

+UINTN

+SetIdtEntry (

+  IN  UINTN                       FunctionPointer,

+  OUT INTERRUPT_GATE_DESCRIPTOR   *IdtEntry

+  );

+

+/**

+  Allocate EfiACPIMemoryNVS below 4G memory address.

+

+  This function allocates EfiACPIMemoryNVS below 4G memory address.

+

+  @param  Size         Size of memory to allocate.

+  

+  @return Allocated address for output.

+

+**/

+VOID*

+AllocateAcpiNvsMemoryBelow4G (

+  IN   UINTN   Size

+  );

+

+/**

+  Sends INIT-SIPI-SIPI to specific AP, and make it work on procedure specified by ApFunction.

+

+  This function sends INIT-SIPI-SIPI to specific AP, and make it work on procedure specified by ApFunction.

+

+  @param  Broadcast   If TRUE, broadcase IPI to all APs; otherwise, send to specified AP.

+  @param  ApicID      The Local APIC ID of the specified AP.

+  @param  ApFunction  The procedure for all APs to work on.

+

+**/

+VOID

+SendInitSipiSipiIpis (

+  IN BOOLEAN            Broadcast,

+  IN UINT32             ApicID,

+  IN AP_PROCEDURE       ApFunction

+  );

+

+/**

+  Dispatches task to AP.

+

+  This function dispatches task to AP. The BSP waits until specified APs have finished.

+

+  @param  Broadcast   If TRUE, send task to all APs; otherwise, send to specified AP.

+  @param  ApicID      The Local APIC ID of the specified AP. If Broadcast is TRUE, it is ignored.

+  @param  Procedure   The procedure for AP to work on.

+

+**/

+VOID

+DispatchAPAndWait (

+  IN BOOLEAN             Broadcast,

+  IN UINT32              ApicID,

+  IN AP_PROCEDURE        Procedure

+  );

+

+/**

+  Installs MP Services Protocol and register related timer event.

+  

+  This function installs MP Services Protocol and register related timer event.

+

+**/

+VOID

+InstallMpServicesProtocol (

+  VOID

+  );

+

+/**

+  Protocol notification that is fired when LegacyBios protocol is installed.

+

+  Re-allocate a wakeup buffer from E/F segment because the previous wakeup buffer

+  under 640K won't be preserved by the legacy OS.

+

+  @param  Event                 The triggered event.

+  @param  Context               Context for this event.

+**/

+VOID

+EFIAPI

+ReAllocateMemoryForAP (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  );

+

+/**

+  Fixup jump instructions in the AP startup code.

+

+  @param AddressMap    Pointer to MP_ASSEMBLY_ADDRESS_MAP.

+  @param TargetBuffer  Target address of the startup vector.

+**/

+VOID

+RedirectFarJump (

+  IN MP_ASSEMBLY_ADDRESS_MAP *AddressMap,

+  IN EFI_PHYSICAL_ADDRESS    TargetBuffer

+  );

+

+/**

+  Protocol notification that will wake up and place AP to the suitable state

+  before booting to OS.

+

+  @param  Event                 The triggered event.

+  @param  Context               Context for this event.

+**/

+VOID

+EFIAPI

+ChangeApLoopModeCallBack (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  );

+

+/**

+  Get mointor data address for specified processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+  @return Pointer to monitor data.

+**/

+MONITOR_MWAIT_DATA *

+EFIAPI

+GetMonitorDataAddress (

+  IN UINTN  ProcessorNumber

+  );

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/MpService.c b/IA32FamilyCpuBasePkg/CpuMpDxe/MpService.c
new file mode 100644
index 0000000..d15a3cc
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/MpService.c
@@ -0,0 +1,1478 @@
+/** @file

+

+  Implementation of MP Services Protocol

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  MpService.c

+

+**/

+

+#include "MpService.h"

+#include "Cpu.h"

+

+EFI_MP_SERVICES_PROTOCOL     mMpService = {

+  GetNumberOfProcessors,

+  GetProcessorInfo,

+  StartupAllAPs,

+  StartupThisAP,

+  SwitchBSP,

+  EnableDisableAP,

+  WhoAmI

+};

+

+BOOLEAN            mStopCheckAPsStatus  = FALSE;

+BOOLEAN            mBspSwitched         = FALSE;

+UINTN              mNewProcessorNumber  = 0;

+MONITOR_MWAIT_DATA *mMonitorDataAddress = NULL;

+

+/**

+  Implementation of GetNumberOfProcessors() service of MP Services Protocol.

+

+  This service retrieves the number of logical processor in the platform

+  and the number of those logical processors that are enabled on this boot.

+  This service may only be called from the BSP.

+

+  @param  This                       A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  NumberOfProcessors         Pointer to the total number of logical processors in the system,

+                                     including the BSP and disabled APs.

+  @param  NumberOfEnabledProcessors  Pointer to the number of enabled logical processors that exist

+                                     in system, including the BSP.

+

+  @retval EFI_SUCCESS	               Number of logical processors and enabled logical processors retrieved..

+  @retval EFI_DEVICE_ERROR           Caller processor is AP.

+  @retval EFI_INVALID_PARAMETER      NumberOfProcessors is NULL

+  @retval EFI_INVALID_PARAMETER      NumberOfEnabledProcessors is NULL

+

+**/

+EFI_STATUS

+EFIAPI

+GetNumberOfProcessors (

+  IN  EFI_MP_SERVICES_PROTOCOL     *This,

+  OUT UINTN                        *NumberOfProcessors,

+  OUT UINTN                        *NumberOfEnabledProcessors

+  )

+{

+  UINTN           Index;

+  CPU_DATA_BLOCK  *CpuData;

+  UINT32          ThreadNumber;

+  UINTN           CallerNumber;

+

+  //

+  // Check whether caller processor is BSP

+  //

+  WhoAmI (This, &CallerNumber);

+  if (CallerNumber != mCpuConfigConextBuffer.BspNumber) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  //

+  // Check parameter NumberOfProcessors

+  //

+  if (NumberOfProcessors == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Check parameter NumberOfEnabledProcessors

+  //

+  if (NumberOfEnabledProcessors == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  *NumberOfProcessors = mCpuConfigConextBuffer.NumberOfProcessors;

+

+  //

+  // Count the number of enabled processors

+  //

+  *NumberOfEnabledProcessors = 0;

+  for (Index = 0; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) {

+

+    GetProcessorLocation (

+      Index,

+      NULL,

+      NULL,

+      &ThreadNumber

+      );

+

+    CpuData = &mMPSystemData.CpuData[Index];

+    if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_HT_BIT) != 0) {

+      if (CpuData->State != CpuStateDisabled) {

+        (*NumberOfEnabledProcessors)++;

+      }

+    } else {

+      if (CpuData->State != CpuStateDisabled && ThreadNumber == 0) {

+        (*NumberOfEnabledProcessors)++;

+      }

+    }

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Implementation of GetNumberOfProcessors() service of MP Services Protocol.

+

+  Gets detailed MP-related information on the requested processor at the

+  instant this call is made. This service may only be called from the BSP.

+

+  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  ProcessorNumber       The handle number of processor.

+  @param  ProcessorInfoBuffer   A pointer to the buffer where information for the requested processor is deposited.

+

+  @retval EFI_SUCCESS           Processor information successfully returned.

+  @retval EFI_DEVICE_ERROR      Caller processor is AP.

+  @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL

+  @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist.

+

+**/

+EFI_STATUS

+EFIAPI

+GetProcessorInfo (

+  IN       EFI_MP_SERVICES_PROTOCOL     *This,

+  IN       UINTN                        ProcessorNumber,

+  OUT      EFI_PROCESSOR_INFORMATION    *ProcessorInfoBuffer

+  )

+{

+  CPU_DATA_BLOCK            *CpuData;

+  UINTN                     CallerNumber;

+

+  //

+  // Check whether caller processor is BSP

+  //

+  WhoAmI (This, &CallerNumber);

+  if (CallerNumber != mCpuConfigConextBuffer.BspNumber) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  //

+  // Check parameter ProcessorInfoBuffer

+  //

+  if (ProcessorInfoBuffer == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Check whether processor with the handle specified by ProcessorNumber exists

+  //

+  if (ProcessorNumber >= mCpuConfigConextBuffer.NumberOfProcessors) {

+    return EFI_NOT_FOUND;

+  }

+

+  CpuData = &mMPSystemData.CpuData[ProcessorNumber];

+

+  //

+  // Get Local APIC ID of specified processor

+  //

+  ProcessorInfoBuffer->ProcessorId = GET_CPU_MISC_DATA (ProcessorNumber, ApicID);

+

+  //

+  // Get physical location of specified processor

+  //

+  GetProcessorLocation (

+    ProcessorNumber,

+    &(ProcessorInfoBuffer->Location.Package),

+    &(ProcessorInfoBuffer->Location.Core),

+    &(ProcessorInfoBuffer->Location.Thread)

+    );

+

+  //

+  // Get Status Flag of specified processor

+  //

+  ProcessorInfoBuffer->StatusFlag = 0;

+

+  ProcessorInfoBuffer->StatusFlag |= PROCESSOR_ENABLED_BIT;

+  if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_HT_BIT) == 0) {

+    if (ProcessorInfoBuffer->Location.Thread > 0) {

+      ProcessorInfoBuffer->StatusFlag &= ~PROCESSOR_ENABLED_BIT;

+    }

+  }

+

+  if (CpuData->State == CpuStateDisabled) {

+    ProcessorInfoBuffer->StatusFlag &= ~PROCESSOR_ENABLED_BIT;

+  }

+

+  if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {

+    ProcessorInfoBuffer->StatusFlag |= PROCESSOR_AS_BSP_BIT;

+  }

+

+  if (mMPSystemData.CpuHealthy[ProcessorNumber]) {

+    ProcessorInfoBuffer->StatusFlag |= PROCESSOR_HEALTH_STATUS_BIT;

+  }

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Implementation of StartupAllAPs() service of MP Services Protocol.

+

+  This service lets the caller get all enabled APs to execute a caller-provided function.

+  This service may only be called from the BSP.

+

+  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  Procedure             A pointer to the function to be run on enabled APs of the system.

+  @param  SingleThread          Indicates whether to execute the function simultaneously or one by one..

+  @param  WaitEvent             The event created by the caller.

+                                If it is NULL, then execute in blocking mode.

+                                If it is not NULL, then execute in non-blocking mode.

+  @param  TimeoutInMicroSeconds The time limit in microseconds for this AP to finish the function.

+                                Zero means infinity.

+  @param  ProcedureArgument     Pointer to the optional parameter of the assigned function.

+  @param  FailedCpuList         The list of processor numbers that fail to finish the function before

+                                TimeoutInMicrosecsond expires.

+

+  @retval EFI_SUCCESS           In blocking mode, all APs have finished before the timeout expired.

+  @retval EFI_SUCCESS           In non-blocking mode, function has been dispatched to all enabled APs.

+  @retval EFI_DEVICE_ERROR      Caller processor is AP.

+  @retval EFI_NOT_STARTED       No enabled AP exists in the system.

+  @retval EFI_NOT_READY         Any enabled AP is busy.

+  @retval EFI_TIMEOUT           In blocking mode, The timeout expired before all enabled APs have finished.

+  @retval EFI_INVALID_PARAMETER Procedure is NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+StartupAllAPs (

+  IN  EFI_MP_SERVICES_PROTOCOL   *This,

+  IN  EFI_AP_PROCEDURE           Procedure,

+  IN  BOOLEAN                    SingleThread,

+  IN  EFI_EVENT                  WaitEvent             OPTIONAL,

+  IN  UINTN                      TimeoutInMicroSeconds,

+  IN  VOID                       *ProcedureArgument    OPTIONAL,

+  OUT UINTN                      **FailedCpuList       OPTIONAL

+  )

+{

+  EFI_STATUS      Status;

+  UINTN           ProcessorNumber;

+  CPU_DATA_BLOCK  *CpuData;

+  BOOLEAN         Blocking;

+

+  if (FailedCpuList != NULL) {

+    *FailedCpuList = NULL;

+  }

+

+  //

+  // Check whether caller processor is BSP

+  //

+  WhoAmI (This, &ProcessorNumber);

+  if (ProcessorNumber != mCpuConfigConextBuffer.BspNumber) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  //

+  // Check parameter Procedure

+  //

+  if (Procedure == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Temporarily suppress CheckAPsStatus()

+  //

+  mStopCheckAPsStatus = TRUE;

+

+  //

+  // Check whether all enabled APs are idle.

+  // If any enabled AP is not idle, return EFI_NOT_READY.

+  //

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+

+    CpuData = &mMPSystemData.CpuData[ProcessorNumber];

+

+    mMPSystemData.CpuList[ProcessorNumber] = FALSE;

+    if (ProcessorNumber != mCpuConfigConextBuffer.BspNumber) {

+      if (CpuData->State != CpuStateDisabled) {

+        if (CpuData->State != CpuStateIdle) {

+          mStopCheckAPsStatus = FALSE;

+          return EFI_NOT_READY;

+        } else {

+          //

+          // Mark this processor as responsible for current calling.

+          //

+          mMPSystemData.CpuList[ProcessorNumber] = TRUE;

+        }

+      }

+    }

+  }

+

+  mMPSystemData.FinishCount = 0;

+  mMPSystemData.StartCount  = 0;

+  Blocking                  = FALSE;

+  //

+  // Go through all enabled APs to wakeup them for Procedure.

+  // If in Single Thread mode, then only one AP is woken up, and others are waiting.

+  //

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+

+    CpuData = &mMPSystemData.CpuData[ProcessorNumber];

+    //

+    // Check whether this processor is responsible for current calling.

+    //

+    if (mMPSystemData.CpuList[ProcessorNumber]) {

+

+      mMPSystemData.StartCount++;

+

+      AcquireSpinLock (&CpuData->CpuDataLock);

+      CpuData->State = CpuStateReady;

+      ReleaseSpinLock (&CpuData->CpuDataLock);

+

+      if (!Blocking) {

+        WakeUpAp (

+          ProcessorNumber,

+          Procedure,

+          ProcedureArgument

+          );

+      }

+

+      if (SingleThread) {

+        Blocking = TRUE;

+      }

+    }

+  }

+

+  //

+  // If only BSP exists then return EFI_SUCCESS as no APs to start, else return EFI_NOT_STARTED.

+  //

+  if (mMPSystemData.StartCount == 0) {

+    mStopCheckAPsStatus = FALSE;

+    if (mCpuConfigConextBuffer.NumberOfProcessors == 1)	{

+      return EFI_SUCCESS;

+	}

+    return EFI_NOT_STARTED;

+  }

+

+  //

+  // If WaitEvent is not NULL, execute in non-blocking mode.

+  // BSP saves data for CheckAPsStatus(), and returns EFI_SUCCESS.

+  // CheckAPsStatus() will check completion and timeout periodically.

+  //

+  mMPSystemData.Procedure      = Procedure;

+  mMPSystemData.ProcArguments  = ProcedureArgument;

+  mMPSystemData.SingleThread   = SingleThread;

+  mMPSystemData.FailedCpuList  = FailedCpuList;

+  mMPSystemData.ExpectedTime   = CalculateTimeout (TimeoutInMicroSeconds, &mMPSystemData.CurrentTime);

+  mMPSystemData.WaitEvent      = WaitEvent;

+

+  //

+  // Allow CheckAPsStatus()

+  //

+  mStopCheckAPsStatus = FALSE;

+

+  if (WaitEvent != NULL) {

+    return EFI_SUCCESS;

+  }

+

+  //

+  // If WaitEvent is NULL, execute in blocking mode.

+  // BSP checks APs'state until all APs finish or TimeoutInMicrosecsond expires.

+  //

+  do {

+    Status = CheckAllAPs ();

+  } while (Status == EFI_NOT_READY);

+

+  return Status;

+}

+

+/**

+  Implementation of StartupThisAP() service of MP Services Protocol.

+

+  This service lets the caller get one enabled AP to execute a caller-provided function.

+  This service may only be called from the BSP.

+

+  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  Procedure             A pointer to the function to be run on the designated AP.

+  @param  ProcessorNumber       The handle number of AP..

+  @param  WaitEvent             The event created by the caller.

+                                If it is NULL, then execute in blocking mode.

+                                If it is not NULL, then execute in non-blocking mode.

+  @param  TimeoutInMicroseconds The time limit in microseconds for this AP to finish the function.

+                                Zero means infinity.

+  @param  ProcedureArgument     Pointer to the optional parameter of the assigned function.

+  @param  Finished              Indicates whether AP has finished assigned function.

+                                In blocking mode, it is ignored.

+

+  @retval EFI_SUCCESS           In blocking mode, specified AP has finished before the timeout expires.

+  @retval EFI_SUCCESS           In non-blocking mode, function has been dispatched to specified AP.

+  @retval EFI_DEVICE_ERROR      Caller processor is AP.

+  @retval EFI_TIMEOUT           In blocking mode, the timeout expires before specified AP has finished.

+  @retval EFI_NOT_READY         Specified AP is busy.

+  @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist.

+  @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.

+  @retval EFI_INVALID_PARAMETER Procedure is NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+StartupThisAP (

+  IN  EFI_MP_SERVICES_PROTOCOL   *This,

+  IN  EFI_AP_PROCEDURE           Procedure,

+  IN  UINTN                      ProcessorNumber,

+  IN  EFI_EVENT                  WaitEvent OPTIONAL,

+  IN  UINTN                      TimeoutInMicroseconds,

+  IN  VOID                       *ProcedureArgument OPTIONAL,

+  OUT BOOLEAN                    *Finished OPTIONAL

+  )

+{

+  CPU_DATA_BLOCK  *CpuData;

+  UINTN           CallerNumber;

+  EFI_STATUS      Status;

+

+  if (Finished != NULL) {

+    *Finished = TRUE;

+  }

+

+  //

+  // Check whether caller processor is BSP

+  //

+  WhoAmI (This, &CallerNumber);

+  if (CallerNumber != mCpuConfigConextBuffer.BspNumber) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  //

+  // Check whether processor with the handle specified by ProcessorNumber exists

+  //

+  if (ProcessorNumber >= mCpuConfigConextBuffer.NumberOfProcessors) {

+    return EFI_NOT_FOUND;

+  }

+

+  //

+  // Check whether specified processor is BSP

+  //

+  if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Check parameter Procedure

+  //

+  if (Procedure == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  CpuData = &mMPSystemData.CpuData[ProcessorNumber];

+

+  //

+  // Temporarily suppress CheckAPsStatus()

+  //

+  mStopCheckAPsStatus = TRUE;

+

+  //

+  // Check whether specified AP is disabled

+  //

+  if (CpuData->State == CpuStateDisabled) {

+    mStopCheckAPsStatus = FALSE;

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Check whether specified AP is busy

+  //

+  if (CpuData->State != CpuStateIdle) {

+    mStopCheckAPsStatus = FALSE;

+    return EFI_NOT_READY;

+  }

+

+  //

+  // Wakeup specified AP for Procedure.

+  //

+  AcquireSpinLock (&CpuData->CpuDataLock);

+  CpuData->State = CpuStateReady;

+  ReleaseSpinLock (&CpuData->CpuDataLock);

+

+  WakeUpAp (

+    ProcessorNumber,

+    Procedure,

+    ProcedureArgument

+    );

+

+  //

+  // If WaitEvent is not NULL, execute in non-blocking mode.

+  // BSP saves data for CheckAPsStatus(), and returns EFI_SUCCESS.

+  // CheckAPsStatus() will check completion and timeout periodically.

+  //

+  CpuData->WaitEvent      = WaitEvent;

+  CpuData->Finished       = Finished;

+  CpuData->ExpectedTime   = CalculateTimeout (TimeoutInMicroseconds, &CpuData->CurrentTime);

+

+  //

+  // Allow CheckAPsStatus()

+  //

+  mStopCheckAPsStatus = FALSE;

+

+  if (WaitEvent != NULL) {

+    return EFI_SUCCESS;

+  }

+

+  //

+  // If WaitEvent is NULL, execute in blocking mode.

+  // BSP checks AP's state until it finishes or TimeoutInMicrosecsond expires.

+  //

+  do {

+    Status = CheckThisAP (ProcessorNumber);

+  } while (Status == EFI_NOT_READY);

+

+  return Status;

+}

+

+/**

+  Implementation of SwitchBSP() service of MP Services Protocol.

+

+  This service switches the requested AP to be the BSP from that point onward.

+  This service may only be called from the current BSP.

+

+  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  ProcessorNumber       The handle number of processor.

+  @param  EnableOldBSP          Whether to enable or disable the original BSP.

+

+  @retval EFI_SUCCESS           BSP successfully switched.

+  @retval EFI_DEVICE_ERROR      Caller processor is AP.

+  @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist.

+  @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.

+  @retval EFI_NOT_READY         Specified AP is busy.

+

+**/

+EFI_STATUS

+EFIAPI

+SwitchBSP (

+  IN  EFI_MP_SERVICES_PROTOCOL            *This,

+  IN  UINTN                               ProcessorNumber,

+  IN  BOOLEAN                             EnableOldBSP

+  )

+{

+  EFI_STATUS            Status;

+  BOOLEAN               OldInterruptState;

+  CPU_DATA_BLOCK        *CpuData;

+  CPU_STATE             CpuState;

+  UINTN                 CallerNumber;

+  UINT32                CurrentTimerCount;

+  UINTN                 DivideValue;

+  UINT8                 Vector;

+  BOOLEAN               PeriodicMode;

+  UINT64                CurrentTscValue;

+  UINT64                TimerPeriod;

+

+  //

+  // Check whether caller processor is BSP

+  //

+  WhoAmI (This, &CallerNumber);

+  if (CallerNumber != mCpuConfigConextBuffer.BspNumber) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  //

+  // Check whether processor with the handle specified by ProcessorNumber exists

+  //

+  if (ProcessorNumber >= mCpuConfigConextBuffer.NumberOfProcessors) {

+    return EFI_NOT_FOUND;

+  }

+

+  //

+  // Check whether specified processor is BSP

+  //

+  if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  CpuData = &mMPSystemData.CpuData[ProcessorNumber];

+

+  //

+  // Check whether specified AP is disabled

+  //

+  if (CpuData->State == CpuStateDisabled) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  //

+  // Check whether specified AP is busy

+  //

+  if (CpuData->State != CpuStateIdle) {

+    return EFI_NOT_READY;

+  }

+

+  //

+  // Save current rate of DXE Timer

+  //

+  mTimer->GetTimerPeriod (mTimer, &TimerPeriod);

+

+  //

+  // Disable DXE Timer and drain pending interrupts

+  //

+  mTimer->SetTimerPeriod (mTimer, 0);

+

+  //

+  // Record the current local APIC timer setting of BSP

+  //

+  GetApicTimerState (&DivideValue, &PeriodicMode, &Vector);

+  CurrentTimerCount = GetApicTimerCurrentCount ();

+  DisableApicTimerInterrupt ();

+

+  //

+  // Record the current TSC value

+  //

+  CurrentTscValue = AsmReadTsc ();

+

+  //

+  // Before send both BSP and AP to a procedure to exchange their roles,

+  // interrupt must be disabled. This is because during the exchange role

+  // process, 2 CPU may use 1 stack. If interrupt happens, the stack will

+  // be corrputed, since interrupt return address will be pushed to stack

+  // by hardware.

+  //

+  OldInterruptState = SaveAndDisableInterrupts ();

+  //

+  // Mask LINT0 & LINT1 for the old BSP

+  //

+  DisableLvtInterrupts ();

+  //

+  // Clear the BSP bit of MSR_IA32_APIC_BASE

+  //

+  AsmMsrBitFieldWrite64 (EFI_MSR_IA32_APIC_BASE, N_MSR_BSP_FLAG, N_MSR_BSP_FLAG, 0);

+

+  mMPSystemData.BSPInfo.State  = CPU_SWITCH_STATE_IDLE;

+  mMPSystemData.APInfo.State   = CPU_SWITCH_STATE_IDLE;

+

+  //

+  // Need to wakeUp AP (future BSP).

+  //

+  WakeUpAp (

+    ProcessorNumber,

+    FutureBSPProc,

+    NULL

+    );

+

+  AsmExchangeRole (&mMPSystemData.BSPInfo, &mMPSystemData.APInfo);

+

+  //

+  // The new BSP has come out. Since it carries the register value of the AP, need

+  // to pay attention to variable which are stored in registers (due to optimization)

+  //

+  AsmMsrBitFieldWrite64 (EFI_MSR_IA32_APIC_BASE, N_MSR_BSP_FLAG, N_MSR_BSP_FLAG, 1);

+  ProgramVirtualWireMode ();

+

+  //

+  // Restore local APIC timer setting to new BSP

+  //

+  InitializeApicTimer (DivideValue, CurrentTimerCount, PeriodicMode, Vector);

+

+  //

+  // Restore interrupt state.

+  //

+  SetInterruptState (OldInterruptState);

+

+  //

+  // Enable and restore rate of DXE Timer

+  //

+  mTimer->SetTimerPeriod (mTimer, TimerPeriod);

+

+  CpuData = &mMPSystemData.CpuData[mCpuConfigConextBuffer.BspNumber];

+  while (TRUE) {

+    AcquireSpinLock (&CpuData->CpuDataLock);

+    CpuState = CpuData->State;

+    ReleaseSpinLock (&CpuData->CpuDataLock);

+

+    if (CpuState == CpuStateFinished) {

+      break;

+    }

+  }

+

+  Status              = ChangeCpuState (mCpuConfigConextBuffer.BspNumber, EnableOldBSP, EFI_CPU_CAUSE_USER_SELECTION);

+  mCpuConfigConextBuffer.BspNumber  = ProcessorNumber;

+

+  return Status;

+}

+

+/**

+  Implementation of EnableDisableAP() service of MP Services Protocol.

+

+  This service lets the caller enable or disable an AP.

+  This service may only be called from the BSP.

+

+  @param  This                   A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  ProcessorNumber        The handle number of processor.

+  @param  NewAPState             Indicates whether the newstate of the AP is enabled or disabled.

+  @param  HealthFlag             Indicates new health state of the AP..

+

+  @retval EFI_SUCCESS            AP successfully enabled or disabled.

+  @retval EFI_DEVICE_ERROR       Caller processor is AP.

+  @retval EFI_NOT_FOUND          Processor with the handle specified by ProcessorNumber does not exist.

+  @retval EFI_INVALID_PARAMETERS ProcessorNumber specifies the BSP.

+

+**/

+EFI_STATUS

+EFIAPI

+EnableDisableAP (

+  IN  EFI_MP_SERVICES_PROTOCOL            *This,

+  IN  UINTN                               ProcessorNumber,

+  IN  BOOLEAN                             NewAPState,

+  IN  UINT32                              *HealthFlag OPTIONAL

+  )

+{

+  EFI_STATUS      Status;

+  UINTN           CallerNumber;

+

+  //

+  // Check whether caller processor is BSP

+  //

+  WhoAmI (This, &CallerNumber);

+  if (CallerNumber != mCpuConfigConextBuffer.BspNumber) {

+    return EFI_DEVICE_ERROR;

+  }

+

+  //

+  // Check whether processor with the handle specified by ProcessorNumber exists

+  //

+  if (ProcessorNumber >= mCpuConfigConextBuffer.NumberOfProcessors) {

+    return EFI_NOT_FOUND;

+  }

+

+  //

+  // Check whether specified processor is BSP

+  //

+  if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  Status  = ChangeCpuState (ProcessorNumber, NewAPState, EFI_CPU_CAUSE_USER_SELECTION);

+

+  if (HealthFlag != NULL) {

+    mMPSystemData.CpuHealthy[ProcessorNumber] = (BOOLEAN) ((*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT) != 0);

+  }

+

+  return Status;

+}

+

+/**

+  Implementation of WhoAmI() service of MP Services Protocol.

+

+  This service lets the caller processor get its handle number.

+  This service may be called from the BSP and APs.

+

+  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  ProcessorNumber       Pointer to the handle number of AP.

+

+  @retval EFI_SUCCESS           Processor number successfully returned.

+  @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL

+

+**/

+EFI_STATUS

+EFIAPI

+WhoAmI (

+  IN  EFI_MP_SERVICES_PROTOCOL            *This,

+  OUT UINTN                               *ProcessorNumber

+  )

+{

+  UINTN   Index;

+  UINT32  ApicID;

+

+  //

+  // Check parameter ProcessorNumber

+  //

+  if (ProcessorNumber == NULL) {

+    return EFI_INVALID_PARAMETER;

+  }

+

+  ApicID = GetApicId ();

+

+  for (Index = 0; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) {

+    if (ApicID == GET_CPU_MISC_DATA (Index, ApicID)) {

+      break;

+    }

+  }

+

+  *ProcessorNumber = Index;

+  return EFI_SUCCESS;

+}

+

+/**

+  Checks APs' status periodically.

+

+  This function is triggerred by timer perodically to check the

+  state of APs for StartupAllAPs() and StartupThisAP() executed

+  in non-blocking mode.

+

+  @param  Event    Event triggered.

+  @param  Context  Parameter passed with the event.

+

+**/

+VOID

+EFIAPI

+CheckAPsStatus (

+  IN  EFI_EVENT                           Event,

+  IN  VOID                                *Context

+  )

+{

+  UINTN           ProcessorNumber;

+  CPU_DATA_BLOCK  *CpuData;

+  EFI_STATUS      Status;

+

+  //

+  // If CheckAPsStatus() is stopped, then return immediately.

+  //

+  if (mStopCheckAPsStatus) {

+    return;

+  }

+

+  //

+  // First, check whether pending StartupAllAPs() exists.

+  //

+  if (mMPSystemData.WaitEvent != NULL) {

+

+    Status = CheckAllAPs ();

+    //

+    // If all APs finish for StartupAllAPs(), signal the WaitEvent for it..

+    //

+    if (Status != EFI_NOT_READY) {

+      Status = gBS->SignalEvent (mMPSystemData.WaitEvent);

+      mMPSystemData.WaitEvent = NULL;

+    }

+  }

+

+  //

+  // Second, check whether pending StartupThisAPs() callings exist.

+  //

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+

+    CpuData = &mMPSystemData.CpuData[ProcessorNumber];

+

+    if (CpuData->WaitEvent == NULL) {

+      continue;

+    }

+

+    Status = CheckThisAP (ProcessorNumber);

+

+    if (Status != EFI_NOT_READY) {

+      gBS->SignalEvent (CpuData->WaitEvent);

+      CpuData->WaitEvent = NULL;

+    }

+  }

+  return ;

+}

+

+/**

+  Checks status of all APs.

+

+  This function checks whether all APs have finished task assigned by StartupAllAPs(),

+  and whether timeout expires.

+

+  @retval EFI_SUCCESS           All APs have finished task assigned by StartupAllAPs().

+  @retval EFI_TIMEOUT           The timeout expires.

+  @retval EFI_NOT_READY         APs have not finished task and timeout has not expired.

+

+**/

+EFI_STATUS

+CheckAllAPs (

+  VOID

+  )

+{

+  UINTN           ProcessorNumber;

+  UINTN           NextProcessorNumber;

+  UINTN           ListIndex;

+  EFI_STATUS      Status;

+  CPU_STATE       CpuState;

+  CPU_DATA_BLOCK  *CpuData;

+

+  NextProcessorNumber = 0;

+

+  //

+  // Go through all APs that are responsible for the StartupAllAPs().

+  //

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+    if (!mMPSystemData.CpuList[ProcessorNumber]) {

+      continue;

+    }

+

+    CpuData = &mMPSystemData.CpuData[ProcessorNumber];

+

+    //

+    //  Check the CPU state of AP. If it is CPU_STATE_FINISHED, then the AP has finished its task.

+    //  Only BSP and corresponding AP access this unit of CPU Data. This means the AP will not modify the

+    //  value of state after setting the it to CPU_STATE_FINISHED, so BSP can safely make use of its value.

+    //

+    AcquireSpinLock (&CpuData->CpuDataLock);

+    CpuState = CpuData->State;

+    ReleaseSpinLock (&CpuData->CpuDataLock);

+

+    if (CpuState == CpuStateFinished) {

+      mMPSystemData.FinishCount++;

+      mMPSystemData.CpuList[ProcessorNumber] = FALSE;

+

+      AcquireSpinLock (&CpuData->CpuDataLock);

+      CpuData->State = CpuStateIdle;

+      ReleaseSpinLock (&CpuData->CpuDataLock);

+

+      //

+      // If in Single Thread mode, then search for the next waiting AP for execution.

+      //

+      if (mMPSystemData.SingleThread) {

+        Status = GetNextWaitingProcessorNumber (&NextProcessorNumber);

+

+        if (!EFI_ERROR (Status)) {

+          WakeUpAp (

+            NextProcessorNumber,

+            mMPSystemData.Procedure,

+            mMPSystemData.ProcArguments

+            );

+        }

+      }

+    }

+  }

+

+  //

+  // If all APs finish, return EFI_SUCCESS.

+  //

+  if (mMPSystemData.FinishCount == mMPSystemData.StartCount) {

+    return EFI_SUCCESS;

+  }

+

+  //

+  // If timeout expires, report timeout.

+  //

+  if (CheckTimeout (&mMPSystemData.CurrentTime, &mMPSystemData.TotalTime, mMPSystemData.ExpectedTime)) {

+    //

+    // If FailedCpuList is not NULL, record all failed APs in it.

+    //

+    if (mMPSystemData.FailedCpuList != NULL) {

+      *mMPSystemData.FailedCpuList = AllocatePool ((mMPSystemData.StartCount - mMPSystemData.FinishCount + 1) * sizeof(UINTN));

+      ASSERT (*mMPSystemData.FailedCpuList != NULL);

+    }

+    ListIndex = 0;

+

+    for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+      //

+      // Check whether this processor is responsible for StartupAllAPs().

+      //

+      if (mMPSystemData.CpuList[ProcessorNumber]) {

+        //

+        // Reset failed APs to idle state

+        //

+        ResetProcessorToIdleState (ProcessorNumber);

+        mMPSystemData.CpuList[ProcessorNumber] = FALSE;

+        if (mMPSystemData.FailedCpuList != NULL) {

+          (*mMPSystemData.FailedCpuList)[ListIndex++] = ProcessorNumber;

+        }

+      }

+    }

+    if (mMPSystemData.FailedCpuList != NULL) {

+      (*mMPSystemData.FailedCpuList)[ListIndex] = END_OF_CPU_LIST;

+    }

+    return EFI_TIMEOUT;

+  }

+  return EFI_NOT_READY;

+}

+

+/**

+  Checks status of specified AP.

+

+  This function checks whether specified AP has finished task assigned by StartupThisAP(),

+  and whether timeout expires.

+

+  @param  ProcessorNumber       The handle number of processor.

+

+  @retval EFI_SUCCESS           Specified AP has finished task assigned by StartupThisAPs().

+  @retval EFI_TIMEOUT           The timeout expires.

+  @retval EFI_NOT_READY         Specified AP has not finished task and timeout has not expired.

+

+**/

+EFI_STATUS

+CheckThisAP (

+  UINTN  ProcessorNumber

+  )

+{

+  CPU_DATA_BLOCK  *CpuData;

+  CPU_STATE       CpuState;

+

+  CpuData = &mMPSystemData.CpuData[ProcessorNumber];

+

+  //

+  //  Check the CPU state of AP. If it is CPU_STATE_FINISHED, then the AP has finished its task.

+  //  Only BSP and corresponding AP access this unit of CPU Data. This means the AP will not modify the

+  //  value of state after setting the it to CPU_STATE_FINISHED, so BSP can safely make use of its value.

+  //

+  AcquireSpinLock (&CpuData->CpuDataLock);

+  CpuState = CpuData->State;

+  ReleaseSpinLock (&CpuData->CpuDataLock);

+

+  //

+  // If the APs finishes for StartupThisAP(), return EFI_SUCCESS.

+  //

+  if (CpuState == CpuStateFinished) {

+

+    AcquireSpinLock (&CpuData->CpuDataLock);

+    CpuData->State = CpuStateIdle;

+    ReleaseSpinLock (&CpuData->CpuDataLock);

+

+    if (CpuData->Finished != NULL) {

+      *(CpuData->Finished) = TRUE;

+    }

+    return EFI_SUCCESS;

+  } else {

+    //

+    // If timeout expires for StartupThisAP(), report timeout.

+    //

+    if (CheckTimeout (&CpuData->CurrentTime, &CpuData->TotalTime, CpuData->ExpectedTime)) {

+

+      if (CpuData->Finished != NULL) {

+        *(CpuData->Finished) = FALSE;

+      }

+      //

+      // Reset failed AP to idle state

+      //

+      ResetProcessorToIdleState (ProcessorNumber);

+

+      return EFI_TIMEOUT;

+    }

+  }

+  return EFI_NOT_READY;

+}

+

+/**

+  Calculate timeout value and return the current performance counter value.

+

+  Calculate the number of performance counter ticks required for a timeout.

+  If TimeoutInMicroseconds is 0, return value is also 0, which is recognized

+  as infinity.

+

+  @param  TimeoutInMicroseconds   Timeout value in microseconds.

+  @param  CurrentTime             Returns the current value of the performance counter.

+

+  @return Expected timestamp counter for timeout.

+          If TimeoutInMicroseconds is 0, return value is also 0, which is recognized

+          as infinity.

+

+**/

+UINT64

+CalculateTimeout (

+  IN  UINTN   TimeoutInMicroseconds,

+  OUT UINT64  *CurrentTime

+  )

+{

+  //

+  // Read the current value of the performance counter

+  //

+  *CurrentTime = GetPerformanceCounter ();

+

+  //

+  // If TimeoutInMicroseconds is 0, return value is also 0, which is recognized

+  // as infinity.

+  //

+  if (TimeoutInMicroseconds == 0) {

+    return 0;

+  }

+

+  //

+  // GetPerformanceCounterProperties () returns the timestamp counter's frequency

+  // in Hz. So multiply the return value with TimeoutInMicroseconds and then divide

+  // it by 1,000,000, to get the number of ticks for the timeout value.

+  //

+  return DivU64x32 (

+           MultU64x64 (

+             GetPerformanceCounterProperties (NULL, NULL),

+             TimeoutInMicroseconds

+             ),

+           1000000

+           );

+}

+

+/**

+  Checks whether timeout expires.

+

+  Check whether the number of ellapsed performance counter ticks required for a timeout condition

+  has been reached.  If Timeout is zero, which means infinity, return value is always FALSE.

+

+  @param  PreviousTime         On input, the value of the performance counter when it was last read.

+                               On output, the current value of the performance counter

+  @param  TotalTime            The total amount of ellapsed time in performance counter ticks.

+  @param  Timeout              The number of performance counter ticks required to reach a timeout condition.

+

+  @retval TRUE                 A timeout condition has been reached.

+  @retval FALSE                A timeout condition has not been reached.

+

+**/

+BOOLEAN

+CheckTimeout (

+  IN OUT UINT64  *PreviousTime,

+  IN     UINT64  *TotalTime,

+  IN     UINT64  Timeout

+  )

+{

+  UINT64  Start;

+  UINT64  End;

+  UINT64  CurrentTime;

+  INT64   Delta;

+  INT64   Cycle;

+

+  if (Timeout == 0) {

+    return FALSE;

+  }

+  GetPerformanceCounterProperties (&Start, &End);

+  Cycle = End - Start;

+  if (Cycle < 0) {

+    Cycle = -Cycle;

+  }

+  Cycle++;

+  CurrentTime = GetPerformanceCounter();

+  Delta = (INT64) (CurrentTime - *PreviousTime);

+  if (Start > End) {

+    Delta = -Delta;

+  }

+  if (Delta < 0) {

+    Delta += Cycle;

+  }

+  *TotalTime += Delta;

+  *PreviousTime = CurrentTime;

+  if (*TotalTime > Timeout) {

+    return TRUE;

+  }

+  return FALSE;

+}

+

+/**

+  Searches for the next waiting AP.

+

+  Search for the next AP that is put in waiting state by single-threaded StartupAllAPs().

+

+  @param  NextProcessorNumber  Pointer to the processor number of the next waiting AP.

+

+  @retval EFI_SUCCESS          The next waiting AP has been found.

+  @retval EFI_NOT_FOUND        No waiting AP exists.

+

+**/

+EFI_STATUS

+GetNextWaitingProcessorNumber (

+  OUT UINTN                               *NextProcessorNumber

+  )

+{

+  UINTN           ProcessorNumber;

+

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+

+    if (mMPSystemData.CpuList[ProcessorNumber]) {

+      *NextProcessorNumber = ProcessorNumber;

+      return EFI_SUCCESS;

+    }

+  }

+

+  return EFI_NOT_FOUND;

+}

+

+/**

+  Worker function for SwitchBSP().

+

+  Worker function for SwitchBSP(), assigned to the AP which is intended to become BSP.

+

+  @param  Buffer  Not used.

+

+**/

+VOID

+EFIAPI

+FutureBSPProc (

+  IN  VOID     *Buffer

+  )

+{

+  AsmExchangeRole (&mMPSystemData.APInfo, &mMPSystemData.BSPInfo);

+  return ;

+}

+

+/**

+  Worker function of EnableDisableAP ()

+

+  Worker function of EnableDisableAP (). Changes state of specified processor.

+

+  @param  ProcessorNumber Processor number of specified AP.

+  @param  NewState        Desired state of the specified AP.

+  @param  Cause           The cause to change AP's state.

+

+  @retval EFI_SUCCESS     AP's state successfully changed.

+

+**/

+EFI_STATUS

+ChangeCpuState (

+  IN     UINTN                      ProcessorNumber,

+  IN     BOOLEAN                    NewState,

+  IN     EFI_CPU_STATE_CHANGE_CAUSE Cause

+  )

+{

+  CPU_DATA_BLOCK                              *CpuData;

+  EFI_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA  ErrorData;

+

+  CpuData = &mMPSystemData.CpuData[ProcessorNumber];

+

+  mMPSystemData.DisableCause[ProcessorNumber] = Cause;

+

+  if (!NewState) {

+    AcquireSpinLock (&CpuData->CpuDataLock);

+    CpuData->State = CpuStateDisabled;

+    ReleaseSpinLock (&CpuData->CpuDataLock);

+

+    ErrorData.Cause             = Cause;

+    ErrorData.SoftwareDisabled  = TRUE;

+

+    REPORT_STATUS_CODE_EX (

+      EFI_ERROR_MINOR | EFI_ERROR_CODE,

+      EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_EC_DISABLED,

+      (UINT32) ProcessorNumber,

+      NULL,

+      NULL,

+      (UINT8 *) &ErrorData + sizeof (EFI_STATUS_CODE_DATA),

+      sizeof (EFI_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA) - sizeof (EFI_STATUS_CODE_DATA)

+      );

+  } else {

+    AcquireSpinLock (&CpuData->CpuDataLock);

+    CpuData->State = CpuStateIdle;

+    ReleaseSpinLock (&CpuData->CpuDataLock);

+  }

+

+  return EFI_SUCCESS;

+}

+

+ /**

+  C function for AP execution.

+

+  The AP startup code jumps to this C function after switching to flat32 model.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+EFIAPI

+ApProcEntry (

+  IN UINTN  ProcessorNumber

+  )

+{

+  if (mApFunction != NULL) {

+    (*mApFunction) (ProcessorNumber);

+  }

+}

+

+/**

+  Wrapper function for all procedures assigned to AP.

+

+  Wrapper function for all procedures assigned to AP via MP service protocol.

+  It controls states of AP and invokes assigned precedure.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+ApProcWrapper (

+  IN UINTN  ProcessorNumber

+  )

+{

+  EFI_AP_PROCEDURE         Procedure;

+  VOID                     *Parameter;

+  CPU_DATA_BLOCK           *CpuData;

+  MONITOR_MWAIT_DATA       *MonitorAddr;

+

+  //

+  // Program virtual wire mode and Local APIC timer for AP, since it will be lost after AP wake up

+  //

+  ProgramVirtualWireMode ();

+  DisableLvtInterrupts ();

+  InitializeApicTimer (mLocalApicTimerDivisor, mLocalApicTimerInitialCount, FALSE, 0);

+

+  //

+  // Initialize Debug Agent to support source level debug on AP code.

+  //

+  InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_AP, NULL, NULL);

+

+  //

+  // Call SetProcessorRegister() to restore register setting,

+  // for some registers are cleared by INIT signal.

+  //

+  SetProcessorRegister (ProcessorNumber);

+

+  CpuData = &mMPSystemData.CpuData[ProcessorNumber];

+

+  AcquireSpinLock (&CpuData->CpuDataLock);

+  CpuData->State = CpuStateBusy;

+  ReleaseSpinLock (&CpuData->CpuDataLock);

+

+  //

+  // Now let us check it out.

+  //

+  AcquireSpinLock (&CpuData->CpuDataLock);

+  Procedure = CpuData->Procedure;

+  Parameter = CpuData->Parameter;

+  ReleaseSpinLock (&CpuData->CpuDataLock);

+

+  if (Procedure != NULL) {

+

+    Procedure (Parameter);

+

+    AcquireSpinLock (&CpuData->CpuDataLock);

+    CpuData->Procedure = NULL;

+    ReleaseSpinLock (&CpuData->CpuDataLock);

+  }

+

+  //

+  // Update signal once finishing AP task

+  //

+  MonitorAddr = GetMonitorDataAddress (ProcessorNumber);

+  MonitorAddr->StartupApSignal = 0;

+

+  //

+  // if BSP is switched to AP, it continue execute from here, but it carries register state

+  // of the old AP, so need to reload CpuData (might be stored in a register after compiler

+  // optimization) to make sure it points to the right data

+  //

+  if (Procedure == FutureBSPProc) {

+    mBspSwitched = TRUE;

+    WhoAmI (&mMpService, &mNewProcessorNumber);

+    CpuData = &mMPSystemData.CpuData[mNewProcessorNumber];

+    mMonitorDataAddress = GetMonitorDataAddress (mNewProcessorNumber);

+    //

+    // Copy the monitor data structure of the old AP into the AP stack of the new AP.

+    //

+    CopyMem (mMonitorDataAddress, MonitorAddr, sizeof (MONITOR_MWAIT_DATA));

+  }

+

+  AcquireSpinLock (&CpuData->CpuDataLock);

+  CpuData->State = CpuStateFinished;

+  ReleaseSpinLock (&CpuData->CpuDataLock);

+}

+

+/**

+  Function to wake up a specified AP and assign procedure to it.

+

+  Function to wake up a specified AP and assign procedure to it.

+

+  @param  ProcessorNumber  Handle number of the specified processor.

+  @param  Procedure        Procedure to assign.

+  @param  ProcArguments    Argument for Procedure.

+

+**/

+VOID

+WakeUpAp (

+  IN   UINTN                 ProcessorNumber,

+  IN   EFI_AP_PROCEDURE      Procedure,

+  IN   VOID                  *ProcArguments

+  )

+{

+  CPU_DATA_BLOCK           *CpuData;

+  MONITOR_MWAIT_DATA       *MonitorAddr;

+

+  CpuData = &mMPSystemData.CpuData[ProcessorNumber];

+

+  AcquireSpinLock (&CpuData->CpuDataLock);

+  CpuData->Parameter  = ProcArguments;

+  CpuData->Procedure  = Procedure;

+  ReleaseSpinLock (&CpuData->CpuDataLock);

+

+  //

+  // Check AP wakeup manner, update signal to wake up AP 

+  //

+  MonitorAddr = GetMonitorDataAddress (ProcessorNumber);

+

+  //

+  // Check AP Loop mode

+  //

+  if (MonitorAddr->ApLoopMode == ApInHltLoop) {

+    //

+    // Save new the AP Loop mode

+    //

+    MonitorAddr->ApLoopMode = mExchangeInfo->ApLoopMode;

+    SendInitSipiSipiIpis (

+      FALSE,

+      GET_CPU_MISC_DATA (ProcessorNumber, ApicID),

+      ApProcWrapper

+      );

+

+  } else if (MonitorAddr->ApLoopMode == ApInMwaitLoop ||

+             MonitorAddr->ApLoopMode == ApInRunLoop) {

+    //

+    // Save new the AP Loop mode

+    //

+    MonitorAddr->ApLoopMode = mExchangeInfo->ApLoopMode;

+    mApFunction = ApProcWrapper;

+    //

+    // AP is in Mwait C1 state

+    //

+    MonitorAddr->MwaitTargetCstate = 0;  

+    MonitorAddr->StartupApSignal = STARTUP_AP_SIGNAL | (UINT16) ProcessorNumber;

+

+  } else {

+

+    ASSERT (FALSE);

+  }

+

+}

+

+/**

+  Reset an AP to Idle state.

+  

+  Any task being executed by the AP will be aborted and the AP 

+  will be waiting for a new task in Wait-For-SIPI state.

+

+  @param ProcessorNumber  The handle number of processor.

+**/

+VOID

+ResetProcessorToIdleState (

+  UINTN      ProcessorNumber

+  )

+{

+  CPU_DATA_BLOCK  *CpuData;

+

+  SendInitSipiSipiIpis (

+    FALSE,

+    GET_CPU_MISC_DATA (ProcessorNumber, ApicID),

+    NULL

+    );

+

+  CpuData = &mMPSystemData.CpuData[ProcessorNumber];

+

+  AcquireSpinLock (&CpuData->CpuDataLock);

+  CpuData->State = CpuStateIdle;

+  ReleaseSpinLock (&CpuData->CpuDataLock);

+}

+

+/**

+  Check whether any AP is running for assigned task.

+

+  @retval TRUE           Some APs are running.

+  @retval FALSE          No AP is running.

+**/

+BOOLEAN

+ApRunning (

+  VOID

+  )

+{

+  CPU_DATA_BLOCK  *CpuData;

+  UINTN           ProcessorNumber;

+

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+    CpuData = &mMPSystemData.CpuData[ProcessorNumber];

+    if (ProcessorNumber != mCpuConfigConextBuffer.BspNumber) {

+      if (CpuData->State != CpuStateIdle && CpuData->State != CpuStateDisabled) {

+        return TRUE;

+      }

+    }

+  }

+  return FALSE;

+}

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/MpService.h b/IA32FamilyCpuBasePkg/CpuMpDxe/MpService.h
new file mode 100644
index 0000000..6799dff
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/MpService.h
@@ -0,0 +1,554 @@
+/** @file

+

+  Include file for MP Services Protocol

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  MpService.h

+

+**/

+

+#ifndef _MP_SERVICE_H_

+#define _MP_SERVICE_H_

+

+#include "MpCommon.h"

+

+#define CPU_CHECK_AP_INTERVAL                 0x10  // microseconds

+//

+//  The MP data structure follows.

+//

+#define CPU_SWITCH_STATE_IDLE   0

+#define CPU_SWITCH_STATE_STORED 1

+#define CPU_SWITCH_STATE_LOADED 2

+

+extern EFI_MP_SERVICES_PROTOCOL     mMpService;

+extern EFI_TIMER_ARCH_PROTOCOL      *mTimer;

+

+typedef struct {

+  UINT8             State;        // offset 0

+  UINTN             StackPointer; // offset 4 / 8

+  IA32_DESCRIPTOR   Gdtr;         // offset 8 / 16

+  IA32_DESCRIPTOR   Idtr;         // offset 14 / 26

+} CPU_EXCHANGE_ROLE_INFO;

+

+typedef enum {

+  CpuStateIdle,

+  CpuStateReady,

+  CpuStateBusy,

+  CpuStateFinished,

+  CpuStateDisabled

+} CPU_STATE;

+

+//

+// Define Individual Processor Data block.

+//

+typedef struct {

+  EFI_AP_PROCEDURE volatile      Procedure;

+  VOID* volatile                 Parameter;

+

+  EFI_EVENT                      WaitEvent;

+  BOOLEAN                        *Finished;

+  UINT64                         ExpectedTime;

+  UINT64                         CurrentTime;

+  UINT64                         TotalTime;

+

+  SPIN_LOCK                      CpuDataLock;

+  CPU_STATE volatile             State;

+

+} CPU_DATA_BLOCK;

+

+//

+// Define MP data block which consumes individual processor block.

+//

+typedef struct {

+  SPIN_LOCK                   APSerializeLock;

+

+  CPU_EXCHANGE_ROLE_INFO      BSPInfo;

+  CPU_EXCHANGE_ROLE_INFO      APInfo;

+

+  EFI_EVENT                   CheckAPsEvent;

+

+  UINTN                       FinishCount;

+  UINTN                       StartCount;

+

+  BOOLEAN                     CpuList[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];

+

+  EFI_AP_PROCEDURE            Procedure;

+  VOID                        *ProcArguments;

+  BOOLEAN                     SingleThread;

+  EFI_EVENT                   WaitEvent;

+  UINTN                       **FailedCpuList;

+  UINT64                      ExpectedTime;

+  UINT64                      CurrentTime;

+  UINT64                      TotalTime;

+

+  CPU_DATA_BLOCK              CpuData[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];

+  EFI_CPU_STATE_CHANGE_CAUSE  DisableCause[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];

+  BOOLEAN                     CpuHealthy[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];

+

+} MP_SYSTEM_DATA;

+

+typedef struct {

+  ACPI_CPU_DATA              AcpiCpuData;

+  IA32_DESCRIPTOR            GdtrProfile;

+  IA32_DESCRIPTOR            IdtrProfile;

+} MP_CPU_SAVED_DATA;

+

+extern MP_SYSTEM_DATA                   mMPSystemData;

+

+/**

+  Implementation of GetNumberOfProcessors() service of MP Services Protocol.

+

+  This service retrieves the number of logical processor in the platform

+  and the number of those logical processors that are enabled on this boot.

+  This service may only be called from the BSP.

+

+  @param  This                       A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  NumberOfCPUs               Pointer to the total number of logical processors in the system,

+                                     including the BSP and disabled APs.

+  @param  NumberOfEnabledCPUs        Pointer to the number of enabled logical processors that exist

+                                     in system, including the BSP.

+

+  @retval EFI_SUCCESS	               Number of logical processors and enabled logical processors retrieved..

+  @retval EFI_DEVICE_ERROR           Caller processor is AP.

+  @retval EFI_INVALID_PARAMETER      NumberOfProcessors is NULL

+  @retval EFI_INVALID_PARAMETER      NumberOfEnabledProcessors is NULL

+

+**/

+EFI_STATUS

+EFIAPI

+GetNumberOfProcessors (

+  IN  EFI_MP_SERVICES_PROTOCOL            *This,

+  OUT UINTN                               *NumberOfCPUs,

+  OUT UINTN                               *NumberOfEnabledCPUs

+  );

+

+/**

+  Implementation of GetNumberOfProcessors() service of MP Services Protocol.

+

+  Gets detailed MP-related information on the requested processor at the

+  instant this call is made. This service may only be called from the BSP.

+

+  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  ProcessorNumber       The handle number of processor.

+  @param  ProcessorInfoBuffer   A pointer to the buffer where information for the requested processor is deposited.

+

+  @retval EFI_SUCCESS           Processor information successfully returned.

+  @retval EFI_DEVICE_ERROR      Caller processor is AP.

+  @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL

+  @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist. 

+

+**/

+EFI_STATUS

+EFIAPI

+GetProcessorInfo (

+  IN       EFI_MP_SERVICES_PROTOCOL     *This,

+  IN       UINTN                        ProcessorNumber,

+  OUT      EFI_PROCESSOR_INFORMATION    *ProcessorInfoBuffer

+  );

+

+/**

+  Implementation of StartupAllAPs() service of MP Services Protocol.

+

+  This service lets the caller get all enabled APs to execute a caller-provided function.

+  This service may only be called from the BSP.

+

+  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  Procedure             A pointer to the function to be run on enabled APs of the system.

+  @param  SingleThread          Indicates whether to execute the function simultaneously or one by one..

+  @param  WaitEvent             The event created by the caller.

+                                If it is NULL, then execute in blocking mode.

+                                If it is not NULL, then execute in non-blocking mode.

+  @param  TimeoutInMicroSeconds The time limit in microseconds for this AP to finish the function.

+                                Zero means infinity.

+  @param  ProcedureArgument     Pointer to the optional parameter of the assigned function.

+  @param  FailedCpuList         The list of processor numbers that fail to finish the function before

+                                TimeoutInMicrosecsond expires.

+

+  @retval EFI_SUCCESS           In blocking mode, all APs have finished before the timeout expired. 

+  @retval EFI_SUCCESS           In non-blocking mode, function has been dispatched to all enabled APs.

+  @retval EFI_DEVICE_ERROR      Caller processor is AP.

+  @retval EFI_NOT_STARTED       No enabled AP exists in the system.

+  @retval EFI_NOT_READY         Any enabled AP is busy.

+  @retval EFI_TIMEOUT           In blocking mode, The timeout expired before all enabled APs have finished.

+  @retval EFI_INVALID_PARAMETER Procedure is NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+StartupAllAPs (

+  IN  EFI_MP_SERVICES_PROTOCOL   *This,

+  IN  EFI_AP_PROCEDURE           Procedure,

+  IN  BOOLEAN                    SingleThread,

+  IN  EFI_EVENT                  WaitEvent             OPTIONAL,

+  IN  UINTN                      TimeoutInMicroSeconds,

+  IN  VOID                       *ProcedureArgument    OPTIONAL,

+  OUT UINTN                      **FailedCpuList       OPTIONAL

+  );

+

+/**

+  Implementation of StartupThisAP() service of MP Services Protocol.

+

+  This service lets the caller get one enabled AP to execute a caller-provided function.

+  This service may only be called from the BSP.

+

+  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  Procedure             A pointer to the function to be run on the designated AP.

+  @param  ProcessorNumber       The handle number of AP..

+  @param  WaitEvent             The event created by the caller.

+                                If it is NULL, then execute in blocking mode.

+                                If it is not NULL, then execute in non-blocking mode.

+  @param  TimeoutInMicroseconds The time limit in microseconds for this AP to finish the function.

+                                Zero means infinity.

+  @param  ProcedureArgument     Pointer to the optional parameter of the assigned function.

+  @param  Finished              Indicates whether AP has finished assigned function.

+                                In blocking mode, it is ignored.

+

+  @retval EFI_SUCCESS           In blocking mode, specified AP has finished before the timeout expires.

+  @retval EFI_SUCCESS           In non-blocking mode, function has been dispatched to specified AP.

+  @retval EFI_DEVICE_ERROR      Caller processor is AP.

+  @retval EFI_TIMEOUT           In blocking mode, the timeout expires before specified AP has finished.

+  @retval EFI_NOT_READY         Specified AP is busy.

+  @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist.

+  @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.

+  @retval EFI_INVALID_PARAMETER Procedure is NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+StartupThisAP (

+  IN  EFI_MP_SERVICES_PROTOCOL   *This,

+  IN  EFI_AP_PROCEDURE           Procedure,

+  IN  UINTN                      ProcessorNumber,

+  IN  EFI_EVENT                  WaitEvent OPTIONAL,

+  IN  UINTN                      TimeoutInMicroseconds,

+  IN  VOID                       *ProcedureArgument OPTIONAL,

+  OUT BOOLEAN                    *Finished OPTIONAL

+  );

+

+/**

+  Implementation of SwitchBSP() service of MP Services Protocol.

+

+  This service switches the requested AP to be the BSP from that point onward.

+  This service may only be called from the current BSP.

+

+  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  ProcessorNumber       The handle number of processor.

+  @param  OldBSPState           Whether to enable or disable the original BSP.

+

+  @retval EFI_SUCCESS           BSP successfully switched.

+  @retval EFI_DEVICE_ERROR      Caller processor is AP.

+  @retval EFI_NOT_FOUND         Processor with the handle specified by ProcessorNumber does not exist.

+  @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP.

+  @retval EFI_NOT_READY         Specified AP is busy.

+

+**/

+EFI_STATUS

+EFIAPI

+SwitchBSP (

+  IN  EFI_MP_SERVICES_PROTOCOL            *This,

+  IN  UINTN                               ProcessorNumber,

+  IN  BOOLEAN                             OldBSPState

+  );

+

+/**

+  Implementation of EnableDisableAP() service of MP Services Protocol.

+

+  This service lets the caller enable or disable an AP.

+  This service may only be called from the BSP.

+

+  @param  This                   A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  ProcessorNumber        The handle number of processor.

+  @param  NewAPState             Indicates whether the newstate of the AP is enabled or disabled.

+  @param  HealthFlag             Indicates new health state of the AP..

+

+  @retval EFI_SUCCESS            AP successfully enabled or disabled.

+  @retval EFI_DEVICE_ERROR       Caller processor is AP.

+  @retval EFI_NOT_FOUND          Processor with the handle specified by ProcessorNumber does not exist.

+  @retval EFI_INVALID_PARAMETERS ProcessorNumber specifies the BSP.

+  

+**/

+EFI_STATUS

+EFIAPI

+EnableDisableAP (

+  IN  EFI_MP_SERVICES_PROTOCOL            *This,

+  IN  UINTN                               ProcessorNumber,

+  IN  BOOLEAN                             NewAPState,

+  IN  UINT32                              *HealthFlag OPTIONAL

+  );

+

+/**

+  Implementation of WhoAmI() service of MP Services Protocol.

+

+  This service lets the caller processor get its handle number.

+  This service may be called from the BSP and APs.

+

+  @param  This                  A pointer to the EFI_MP_SERVICES_PROTOCOL instance.

+  @param  ProcessorNumber       Pointer to the handle number of AP.

+

+  @retval EFI_SUCCESS           Processor number successfully returned.

+  @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL

+

+**/

+EFI_STATUS

+EFIAPI

+WhoAmI (

+  IN  EFI_MP_SERVICES_PROTOCOL            *This,

+  OUT UINTN                               *ProcessorNumber

+  );

+

+/**

+  This function is called by both the BSP and the AP which is to become the BSP to 

+  Exchange execution context including stack between them. After return from this

+  function, the BSP becomes AP and the AP becomes the BSP.

+

+  @param MyInfo      Pointer to buffer holding the exchanging information for the executing processor.

+  @param OthersInfo  Pointer to buffer holding the exchanging information for the peer.

+**/

+VOID

+EFIAPI

+AsmExchangeRole (

+  IN   CPU_EXCHANGE_ROLE_INFO    *MyInfo,

+  IN   CPU_EXCHANGE_ROLE_INFO    *OthersInfo

+  );

+

+/**

+  Worker function for SwitchBSP().

+

+  Worker function for SwitchBSP(), assigned to the AP which is intended to become BSP.

+

+  @param  Buffer  Not used.

+

+**/

+VOID

+EFIAPI

+FutureBSPProc (

+  IN  VOID     *Buffer

+  );

+

+/**

+  Worker function of EnableDisableAP ()

+

+  Worker function of EnableDisableAP (). Changes state of specified processor.

+

+  @param  CpuNumber       Processor number of specified AP.

+  @param  NewState        Desired state of the specified AP.

+  @param  Cause           The cause to change AP's state.

+

+  @retval EFI_SUCCESS     AP's state successfully changed.

+

+**/

+EFI_STATUS

+ChangeCpuState (

+  IN     UINTN                      CpuNumber,

+  IN     BOOLEAN                    NewState,

+  IN     EFI_CPU_STATE_CHANGE_CAUSE Cause

+  );

+

+/**

+  Checks APs' status periodically.

+

+  This function is triggerred by timer perodically to check the

+  state of APs for StartupAllAPs() and StartupThisAP() executed

+  in non-blocking mode.

+

+  @param  Event    Event triggered.

+  @param  Context  Parameter passed with the event.

+

+**/

+VOID

+EFIAPI

+CheckAPsStatus (

+  IN  EFI_EVENT                           Event,

+  IN  VOID                                *Context

+  );

+

+/**

+  Checks status of all APs.

+

+  This function checks whether all APs have finished task assigned by StartupAllAPs(),

+  and whether timeout expires.

+

+  @retval EFI_SUCCESS           All APs have finished task assigned by StartupAllAPs().

+  @retval EFI_TIMEOUT           The timeout expires.

+  @retval EFI_NOT_READY         APs have not finished task and timeout has not expired.

+

+**/

+EFI_STATUS

+CheckAllAPs (

+  VOID

+  );

+

+/**

+  Checks status of specified AP.

+

+  This function checks whether specified AP has finished task assigned by StartupThisAP(),

+  and whether timeout expires.

+

+  @param  ProcessorNumber       The handle number of processor.

+

+  @retval EFI_SUCCESS           Specified AP has finished task assigned by StartupThisAPs().

+  @retval EFI_TIMEOUT           The timeout expires.

+  @retval EFI_NOT_READY         Specified AP has not finished task and timeout has not expired.

+

+**/

+EFI_STATUS

+CheckThisAP (

+  UINTN  ProcessorNumber

+  );

+

+/**

+  Calculate timeout value and return the current performance counter value.

+

+  Calculate the number of performance counter ticks required for a timeout.

+  If TimeoutInMicroseconds is 0, return value is also 0, which is recognized

+  as infinity.

+

+  @param  TimeoutInMicroseconds   Timeout value in microseconds.

+  @param  CurrentTime             Returns the current value of the performance counter.

+

+  @return Expected timestamp counter for timeout.

+          If TimeoutInMicroseconds is 0, return value is also 0, which is recognized

+          as infinity.

+

+**/

+UINT64

+CalculateTimeout (

+  IN  UINTN   TimeoutInMicroseconds,

+  OUT UINT64  *CurrentTime

+  );

+

+/**

+  Checks whether timeout expires.

+

+  Check whether the number of ellapsed performance counter ticks required for a timeout condition

+  has been reached.  If Timeout is zero, which means infinity, return value is always FALSE.

+

+  @param  PreviousTime         On input, the value of the performance counter when it was last read.

+                               On output, the current value of the performance counter

+  @param  TotalTime            The total amount of ellapsed time in performance counter ticks.

+  @param  Timeout              The number of performance counter ticks required to reach a timeout condition.

+

+  @retval TRUE                 A timeout condition has been reached.

+  @retval FALSE                A timeout condition has not been reached.

+

+**/

+BOOLEAN

+CheckTimeout (

+  IN OUT UINT64  *PreviousTime,

+  IN     UINT64  *TotalTime,

+  IN     UINT64  Timeout

+  );

+

+/**

+  Searches for the next waiting AP.

+

+  Search for the next AP that is put in waiting state by single-threaded StartupAllAPs().

+

+  @param  NextProcessorNumber  Pointer to the processor number of the next waiting AP.

+

+  @retval EFI_SUCCESS          The next waiting AP has been found.

+  @retval EFI_NOT_FOUND        No waiting AP exists.

+

+**/

+EFI_STATUS

+GetNextWaitingProcessorNumber (

+  OUT UINTN                               *NextProcessorNumber

+  );

+

+ /**

+  C function for AP execution.

+

+  The AP startup code jumps to this C function after switching to flat32 model.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+EFIAPI

+ApProcEntry (

+  IN UINTN  ProcessorNumber

+  );

+

+/**

+  Wrapper function for all procedures assigned to AP.

+

+  Wrapper function for all procedures assigned to AP via MP service protocol.

+  It controls states of AP and invokes assigned precedure.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+ApProcWrapper (

+  IN UINTN  ProcessorNumber

+  );

+

+/**

+  Function to wake up a specified AP and assign procedure to it.

+  

+  Function to wake up a specified AP and assign procedure to it.

+

+  @param  ProcessorNumber  Handle number of the specified processor.

+  @param  Procedure        Procedure to assign.

+  @param  Parameter        Argument for Procedure.

+

+**/

+VOID

+WakeUpAp (

+  IN   UINTN                 ProcessorNumber,

+  IN   EFI_AP_PROCEDURE      Procedure,

+  IN   VOID                  *Parameter

+  );

+

+/**

+  Reset an AP to Idle state.

+  

+  Any task being executed by the AP will be aborted and the AP 

+  will be waiting for a new task in Wait-For-SIPI state.

+

+  @param ProcessorNumber  The handle number of processor.

+**/

+VOID

+ResetProcessorToIdleState (

+  UINTN      ProcessorNumber

+  );

+

+/**

+  Check whether any AP is running for assigned task.

+

+  @retval TRUE           Some APs are running.

+  @retval FALSE          No AP is running.

+**/

+BOOLEAN

+ApRunning (

+  VOID

+  );

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/ProcessorConfig.c b/IA32FamilyCpuBasePkg/CpuMpDxe/ProcessorConfig.c
new file mode 100644
index 0000000..e84315a
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/ProcessorConfig.c
@@ -0,0 +1,571 @@
+/** @file

+  Code for processor configuration.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  ProcessorConfig.c

+

+**/

+

+#include "MpService.h"

+#include "Cpu.h"

+#include "MpApic.h"

+

+MP_SYSTEM_DATA                      mMPSystemData;

+CPU_CONFIG_CONTEXT_BUFFER           mCpuConfigConextBuffer;

+EFI_PHYSICAL_ADDRESS                mStartupVector;

+UINT8                               mPlatformType;

+ACPI_CPU_DATA                       *mAcpiCpuData;

+EFI_HANDLE                          mHandle = NULL;

+MTRR_SETTINGS                       *mMtrrSettings;

+EFI_EVENT                           mSmmConfigurationNotificationEvent;

+EFI_HANDLE                          mImageHandle;

+EFI_TIMER_ARCH_PROTOCOL             *mTimer;

+UINTN                               mLocalApicTimerDivisor;

+UINT32                              mLocalApicTimerInitialCount;

+

+/**

+  Prepares memory region for processor configuration.

+  

+  This function prepares memory region for processor configuration.

+

+**/

+VOID

+PrepareMemoryForConfiguration (

+  VOID

+  )

+{

+  UINTN                NumberOfProcessors;

+  UINTN                Index;

+  MONITOR_MWAIT_DATA   *MonitorData;

+

+  //

+  // Initialize Spin Locks for system

+  //

+  InitializeSpinLock (&mMPSystemData.APSerializeLock);

+  for (Index = 0; Index < PcdGet32(PcdCpuMaxLogicalProcessorNumber); Index++) {

+    InitializeSpinLock (&mMPSystemData.CpuData[Index].CpuDataLock);

+  }

+

+  //

+  // Claim memory for AP stack.

+  //

+  mExchangeInfo->StackStart = AllocateAcpiNvsMemoryBelow4G (PcdGet32(PcdCpuMaxLogicalProcessorNumber) * PcdGet32 (PcdCpuApStackSize));

+  mExchangeInfo->StackSize  = PcdGet32 (PcdCpuApStackSize);

+

+  //

+  // Initialize the Monitor Data structure in APs' stack

+  //

+  for (Index = 0; Index < PcdGet32(PcdCpuMaxLogicalProcessorNumber); Index++) {

+    MonitorData = GetMonitorDataAddress (Index);

+    MonitorData->ApLoopMode = ApInHltLoop;

+  }

+

+  //

+  // Initialize data for CPU configuration context buffer

+  //

+  NumberOfProcessors = mCpuConfigConextBuffer.NumberOfProcessors;

+  mCpuConfigConextBuffer.CollectedDataBuffer  = AllocateZeroPool (sizeof (CPU_COLLECTED_DATA) * NumberOfProcessors);

+  mCpuConfigConextBuffer.FeatureLinkListEntry = AllocateZeroPool (sizeof (LIST_ENTRY) * NumberOfProcessors);

+

+  //

+  // Initialize Processor Feature List for all logical processors.

+  //

+  for (Index = 0; Index < NumberOfProcessors; Index++) {

+    InitializeListHead (&mCpuConfigConextBuffer.FeatureLinkListEntry[Index]);

+  }

+

+  mCpuConfigConextBuffer.RegisterTable   = AllocateAcpiNvsMemoryBelow4G (

+                                            (sizeof (CPU_REGISTER_TABLE) + sizeof (UINTN)) * NumberOfProcessors

+                                            );

+  mCpuConfigConextBuffer.PreSmmInitRegisterTable = AllocateAcpiNvsMemoryBelow4G (

+                                                     (sizeof (CPU_REGISTER_TABLE) + sizeof (UINTN)) * NumberOfProcessors

+                                                     );

+

+  mCpuConfigConextBuffer.SettingSequence = (UINTN *) (((UINTN) mCpuConfigConextBuffer.RegisterTable) + (sizeof (CPU_REGISTER_TABLE) * NumberOfProcessors));

+  for (Index = 0; Index < NumberOfProcessors; Index++) {

+    mCpuConfigConextBuffer.SettingSequence[Index] = Index;

+  }

+

+  //

+  // Set the value for PcdCpuConfigContextBuffer.

+  //

+  mCpuConfigLibConfigConextBuffer = &mCpuConfigConextBuffer;

+  PcdSet64 (PcdCpuConfigContextBuffer, (UINT64) (UINTN) mCpuConfigLibConfigConextBuffer);

+

+  //

+  // Read the platform type from PCD

+  //

+  mPlatformType = PcdGet8 (PcdPlatformType);

+}

+

+/**

+  Event notification that is fired every time a gEfiSmmConfigurationProtocol installs.

+

+  This function configures all logical processors with three-phase architecture.

+

+  @param  Event                 The Event that is being processed, not used.

+  @param  Context               Event Context, not used.

+

+**/

+VOID

+EFIAPI

+SmmConfigurationEventNotify (

+  IN EFI_EVENT  Event,

+  IN VOID       *Context

+  )

+{

+  EFI_STATUS    Status;

+  VOID  *Registration;

+  EFI_SMM_CONFIGURATION_PROTOCOL  *SmmConfiguration;

+

+  //

+  // Make sure this notification is for this handler

+  //

+  Status = gBS->LocateProtocol (&gEfiSmmConfigurationProtocolGuid, NULL, (VOID **)&SmmConfiguration);

+  if (EFI_ERROR (Status)) {

+    return;

+  }

+

+  //

+  // Wakeup APs. Collect data of all processors. BSP polls to

+  // wait for APs' completion.

+  //

+  DataCollectionPhase ();

+  //

+  // With collected data, BSP analyzes processors'configuration

+  // according to user's policy.

+  //

+  AnalysisPhase ();

+

+  //

+  // Wakeup APs. Program registers of all processors, according to

+  // the result of Analysis phase. BSP polls to wait for AP's completion.

+  //

+  SettingPhase ();

+

+  //

+  // Select least-feature procesosr as BSP

+  //

+  if (FeaturePcdGet (PcdCpuSelectLfpAsBspFlag)) {

+    SelectLfpAsBsp ();

+  }

+

+  //

+  // Add SMBIOS Processor Type and Cache Type tables for the CPU.

+  //

+  AddCpuSmbiosTables ();

+

+  //

+  // Save CPU S3 data

+  //

+  SaveCpuS3Data (mImageHandle);

+

+  Status = gBS->SetTimer (

+                  mMPSystemData.CheckAPsEvent,

+                  TimerPeriodic,

+                  10000 * MICROSECOND

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Setup notification on Legacy BIOS Protocol to reallocate AP wakeup

+  //

+  EfiCreateProtocolNotifyEvent (

+    &gEfiLegacyBiosProtocolGuid,

+    TPL_CALLBACK,

+    ReAllocateMemoryForAP,

+    NULL,

+    &Registration

+    );

+}

+

+/**

+  Early MP Initialization.

+  

+  This function does early MP initialization, including MTRR sync and first time microcode load.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+EarlyMpInit (

+  IN UINTN  ProcessorNumber

+  )

+{

+  MtrrSetAllMtrrs (mMtrrSettings);

+

+  CollectBasicProcessorData (ProcessorNumber);

+

+}

+

+/**

+  First phase MP initialization before SMM initialization.

+  

+  @retval EFI_SUCCESS      First phase MP initialization was done successfully.

+  @retval EFI_UNSUPPORTED  There is legacy APIC ID conflict and can't be rsolved in xAPIC mode.

+

+**/

+EFI_STATUS

+ProcessorConfiguration (

+  VOID

+  )

+{

+  EFI_STATUS    Status;

+

+  //

+  // Wakeup APs for the first time, BSP stalls for arbitrary

+  // time for APs' completion. BSP then collects the number

+  // and BIST information of APs.

+  //

+  WakeupAPAndCollectBist ();

+  //

+  // Sort APIC ID of all processors in asending order. Processor number

+  // is assigned in this order to ease MP debug. SMBIOS logic also depends on it.

+  //

+  SortApicId ();

+

+  //

+  // Prepare data in memory for processor configuration

+  //

+  PrepareMemoryForConfiguration ();

+

+  //

+  // Early MP initialization

+  //

+  mMtrrSettings = (MTRR_SETTINGS *)(UINTN)PcdGet64 (PcdCpuMtrrTableAddress);

+  MtrrGetAllMtrrs (mMtrrSettings);

+

+  DispatchAPAndWait (

+    TRUE,

+    0,

+    EarlyMpInit

+    );

+

+  EarlyMpInit (mCpuConfigConextBuffer.BspNumber);

+

+  DEBUG_CODE (

+    //

+    // Verify that all processors have same APIC ID topology. New APIC IDs

+    // were constructed based on this assumption.

+    //

+    UINTN Index;

+    UINT8 PackageIdBitOffset;

+

+    PackageIdBitOffset = mCpuConfigConextBuffer.CollectedDataBuffer[0].PackageIdBitOffset;

+    for (Index = 1; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) {

+      if (PackageIdBitOffset != mCpuConfigConextBuffer.CollectedDataBuffer[Index].PackageIdBitOffset) {

+        ASSERT (FALSE);

+      }

+    }

+  );

+

+  //

+  // Check if there is legacy APIC ID conflict among all processors.

+  //

+  Status = CheckApicId ();

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  //

+  // Assign Package BSP for package scope programming later.

+  //

+  AssignPackageBsp ();

+

+  //

+  // Produce pre-SMM-init register table.

+  //

+  ProducePreSmmInitRegisterTable ();

+

+  //

+  // Early MP initialization step 2

+  //

+  DispatchAPAndWait (

+    TRUE,

+    0,

+    SetPreSmmInitProcessorRegister

+    );

+

+  SetPreSmmInitProcessorRegister (mCpuConfigConextBuffer.BspNumber);

+

+  //

+  // Locate Timer Arch Protocol

+  //

+  Status = gBS->LocateProtocol (&gEfiTimerArchProtocolGuid, NULL, (VOID **) &mTimer);

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Install MP Services Protocol

+  //

+  InstallMpServicesProtocol ();

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Installs MP Services Protocol and register related timer event.

+  

+  This function installs MP Services Protocol and register related timer event.

+

+**/

+VOID

+InstallMpServicesProtocol (

+  VOID

+  )

+{

+  EFI_STATUS    Status;

+

+  //

+  // Create timer event to check AP state for non-blocking execution.

+  //

+  Status = gBS->CreateEvent (

+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,

+                  TPL_CALLBACK,

+                  CheckAPsStatus,

+                  NULL,

+                  &mMPSystemData.CheckAPsEvent

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Now install the MP services protocol.

+  //

+  Status = gBS->InstallProtocolInterface (

+                  &mHandle,

+                  &gEfiMpServiceProtocolGuid,

+                  EFI_NATIVE_INTERFACE,

+                  &mMpService

+                  );

+  ASSERT_EFI_ERROR (Status);

+}

+

+/**

+  Callback function for idle events.

+ 

+  @param  Event                 Event whose notification function is being invoked.

+  @param  Context               The pointer to the notification function's context,

+                                which is implementation-dependent.

+

+**/

+VOID

+EFIAPI

+IdleLoopEventCallback (

+  IN EFI_EVENT                Event,

+  IN VOID                     *Context

+  )

+{

+  CpuSleep ();

+}

+

+/**

+  Entrypoint of CPU MP DXE module.

+  

+  This function is the entrypoint of CPU MP DXE module.

+  It initializes Multi-processor configuration and installs MP Services Protocol.

+

+  @param  ImageHandle   The firmware allocated handle for the EFI image.

+  @param  SystemTable   A pointer to the EFI System Table.

+  

+  @retval EFI_SUCCESS   The entrypoint always returns EFI_SUCCESS.

+

+**/

+EFI_STATUS

+EFIAPI

+MultiProcessorInitialize (

+  IN EFI_HANDLE                            ImageHandle,

+  IN EFI_SYSTEM_TABLE                      *SystemTable

+  )

+{

+  EFI_STATUS  Status;

+  VOID        *Registration;

+  EFI_EVENT   IdleLoopEvent;

+  EFI_EVENT   ExitBootServiceEvent;

+  EFI_EVENT   LegacyToBootEvent;

+

+  mImageHandle = ImageHandle;

+  //

+  // Configure processors with three-phase architecture

+  //

+  Status = ProcessorConfiguration ();

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  //

+  // Install notification callback on SMM Configuration Protocol

+  //

+  mSmmConfigurationNotificationEvent = EfiCreateProtocolNotifyEvent (

+                                         &gEfiSmmConfigurationProtocolGuid,

+                                         TPL_CALLBACK,

+                                         SmmConfigurationEventNotify,

+                                         NULL,

+                                         &Registration

+                                         );

+

+  //

+  // Create EXIT_BOOT_SERIVES Event to set AP to suitable status

+  //

+  Status = gBS->CreateEventEx (

+                  EVT_NOTIFY_SIGNAL,

+                  TPL_NOTIFY,

+                  ChangeApLoopModeCallBack,

+                  NULL,

+                  &gEfiEventExitBootServicesGuid,

+                  &ExitBootServiceEvent

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  //  

+  // Create an event to be signalled when Legacy Boot occurs to set AP to suitable status  

+  //

+  Status = EfiCreateEventLegacyBootEx(

+             TPL_NOTIFY, 

+             ChangeApLoopModeCallBack, 

+             NULL, 

+             &LegacyToBootEvent

+             );

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Setup a callback for idle events

+  //

+  Status = gBS->CreateEventEx (

+                  EVT_NOTIFY_SIGNAL,

+                  TPL_NOTIFY,

+                  IdleLoopEventCallback,

+                  NULL,

+                  &gIdleLoopEventGuid,

+                  &IdleLoopEvent

+                  );

+  ASSERT_EFI_ERROR (Status);

+

+  return EFI_SUCCESS;

+}

+

+/**

+  Wakes up APs for the first time to count their number and collect BIST data.

+

+  This function wakes up APs for the first time to count their number and collect BIST data.

+

+**/

+VOID

+WakeupAPAndCollectBist (

+  VOID

+  )

+{

+  //

+  // Save BSP's Local APIC Timer setting

+  //

+  GetApicTimerState (&mLocalApicTimerDivisor, NULL, NULL);

+  mLocalApicTimerInitialCount = GetApicTimerInitCount ();

+

+  //

+  // Prepare code and data for APs' startup vector

+  //

+  PrepareAPStartupVector ();

+

+  mCpuConfigConextBuffer.NumberOfProcessors = 1;

+  mCpuConfigConextBuffer.BspNumber = 0;

+  //

+  // Item 0 of BistBuffer is for BSP.

+  //

+  mExchangeInfo->BistBuffer[0].ApicId = GetInitialApicId ();

+  

+  SendInitSipiSipiIpis (

+    TRUE,

+    0,

+    NULL

+    );

+

+  //

+  // Wait for task to complete and then exit.

+  //

+  MicroSecondDelay (PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));

+  mExchangeInfo->InitFlag = 0;

+}

+

+

+/**

+  Prepare ACPI NVS memory below 4G memory for use of S3 resume.

+  

+  This function allocates ACPI NVS memory below 4G memory for use of S3 resume,

+  and saves data into the memory region.

+

+  @param  Context   The Context save the info.

+

+**/

+VOID

+SaveCpuS3Data (

+  VOID    *Context

+  )

+{

+  MP_CPU_SAVED_DATA       *MpCpuSavedData;

+

+  //

+  // Allocate ACPI NVS memory below 4G memory for use of S3 resume.

+  //

+  MpCpuSavedData = AllocateAcpiNvsMemoryBelow4G (sizeof (MP_CPU_SAVED_DATA));

+

+  //

+  // Set the value for CPU data

+  //

+  mAcpiCpuData                 = &(MpCpuSavedData->AcpiCpuData);

+  mAcpiCpuData->GdtrProfile    = (EFI_PHYSICAL_ADDRESS) (UINTN) &(MpCpuSavedData->GdtrProfile);

+  mAcpiCpuData->IdtrProfile    = (EFI_PHYSICAL_ADDRESS) (UINTN) &(MpCpuSavedData->IdtrProfile);

+  mAcpiCpuData->StackAddress   = (EFI_PHYSICAL_ADDRESS) (UINTN) mExchangeInfo->StackStart;

+  mAcpiCpuData->StackSize      = PcdGet32 (PcdCpuApStackSize);

+  mAcpiCpuData->MtrrTable      = (EFI_PHYSICAL_ADDRESS) (UINTN) PcdGet64 (PcdCpuMtrrTableAddress);

+  mAcpiCpuData->RegisterTable  = (EFI_PHYSICAL_ADDRESS) (UINTN) mCpuConfigConextBuffer.RegisterTable;

+

+  mAcpiCpuData->PreSmmInitRegisterTable   = (EFI_PHYSICAL_ADDRESS) (UINTN) mCpuConfigConextBuffer.PreSmmInitRegisterTable;

+  mAcpiCpuData->ApMachineCheckHandlerBase = mApMachineCheckHandlerBase;

+  mAcpiCpuData->ApMachineCheckHandlerSize = mApMachineCheckHandlerSize;

+

+  //

+  // Check user's policy for HT enable.

+  //

+  mAcpiCpuData->APState        = FALSE;

+  if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_HT_BIT) != 0) {

+    mAcpiCpuData->APState = TRUE;

+  }

+

+  //

+  // Copy GDTR and IDTR profiles

+  //

+  CopyMem ((VOID *) (UINTN) mAcpiCpuData->GdtrProfile, (VOID *) (UINTN) &mExchangeInfo->GdtrProfile, sizeof (IA32_DESCRIPTOR));

+  CopyMem ((VOID *) (UINTN) mAcpiCpuData->IdtrProfile, (VOID *) (UINTN) &mExchangeInfo->IdtrProfile, sizeof (IA32_DESCRIPTOR));

+

+  mAcpiCpuData->NumberOfCpus  = (UINT32) mCpuConfigConextBuffer.NumberOfProcessors;

+  

+  //

+  // Set the base address of CPU S3 data to PcdCpuS3DataAddress

+  //

+  PcdSet64 (PcdCpuS3DataAddress, (UINT64)(UINTN)mAcpiCpuData); 

+}

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Cache.h b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Cache.h
new file mode 100644
index 0000000..654d5cb
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Cache.h
@@ -0,0 +1,108 @@
+/** @file

+  Include file for record cache subclass data with Smbios protocol.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+**/

+

+#ifndef _CACHE_H_

+#define _CACHE_H_

+

+#include "MpCommon.h"

+

+//

+// Bit field definitions for return registers of CPUID EAX = 4

+//

+// EAX

+#define CPU_CACHE_TYPE_MASK                0x1F

+#define CPU_CACHE_LEVEL_MASK               0xE0

+#define CPU_CACHE_LEVEL_SHIFT              5

+// EBX

+#define CPU_CACHE_LINESIZE_MASK            0xFFF

+#define CPU_CACHE_PARTITIONS_MASK          0x3FF000

+#define CPU_CACHE_PARTITIONS_SHIFT         12

+#define CPU_CACHE_WAYS_MASK                0xFFC00000

+#define CPU_CACHE_WAYS_SHIFT               22

+

+#define CPU_CACHE_L1        1

+#define CPU_CACHE_L2        2

+#define CPU_CACHE_L3        3

+#define CPU_CACHE_L4        4

+#define CPU_CACHE_LMAX      CPU_CACHE_L4

+

+typedef struct {

+  UINT8                         CacheLevel;

+  UINT8                         CacheDescriptor;

+  UINT16                        CacheSizeinKB;

+  CACHE_ASSOCIATIVITY_DATA      Associativity;

+  CACHE_TYPE_DATA               SystemCacheType;

+} CPU_CACHE_CONVERTER;

+

+

+typedef struct {

+  UINT16                        CacheSizeinKB;

+  CACHE_ASSOCIATIVITY_DATA      Associativity;

+  CACHE_TYPE_DATA               SystemCacheType;

+  //

+  // Can extend the structure here.

+  //

+} CPU_CACHE_DATA;

+

+//

+// It is defined for SMBIOS_TABLE_TYPE7.CacheConfiguration.

+//

+typedef struct {

+  UINT16    Level           :3;

+  UINT16    Socketed        :1;

+  UINT16    Reserved2       :1;

+  UINT16    Location        :2;

+  UINT16    Enable          :1;

+  UINT16    OperationalMode :2;

+  UINT16    Reserved1       :6;

+} CPU_CACHE_CONFIGURATION_DATA;

+

+/**

+  Add Cache Information to Type 7 SMBIOS Record.

+  

+  @param[in]    ProcessorNumber     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              ProcessorNumber,

+  OUT EFI_SMBIOS_HANDLE *L1CacheHandle,

+  OUT EFI_SMBIOS_HANDLE *L2CacheHandle,

+  OUT EFI_SMBIOS_HANDLE *L3CacheHandle

+  );

+

+#endif

+

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CacheSubClass.c b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CacheSubClass.c
new file mode 100644
index 0000000..efd5ada
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CacheSubClass.c
@@ -0,0 +1,587 @@
+/** @file

+  Code to record cache subclass data with Smbios protocol.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+**/

+

+#include "Processor.h"

+#include "Cache.h"

+#include <Library/PrintLib.h>

+

+CPU_CACHE_CONVERTER mCacheConverter[] = {

+  {

+    1,

+    0x06,

+    8,

+    CacheAssociativity4Way,

+    CacheTypeInstruction

+  },

+  {

+    1,

+    0x08,

+    16,

+    CacheAssociativity4Way,

+    CacheTypeInstruction

+  },

+  {

+    1,

+    0x0A,

+    8,

+    CacheAssociativity2Way,

+    CacheTypeData

+  },

+  {

+    1,

+    0x0C,

+    16,

+    CacheAssociativity4Way,

+    CacheTypeData

+  },

+  {

+    3,

+    0x22,

+    512,

+    CacheAssociativity4Way,

+    CacheTypeUnified

+  },

+  {

+    3,

+    0x23,

+    1024,

+    CacheAssociativity8Way,

+    CacheTypeUnified

+  },

+  {

+    3,

+    0x25,

+    2048,

+    CacheAssociativity8Way,

+    CacheTypeUnified

+  },

+  {

+    3,

+    0x29,

+    4096,

+    CacheAssociativity8Way,

+    CacheTypeUnified

+  },

+  {

+    1,

+    0x2C,

+    32,

+    CacheAssociativity8Way,

+    CacheTypeData

+  },

+  {

+    1,

+    0x30,

+    32,

+    CacheAssociativity8Way,

+    CacheTypeInstruction

+  },

+  {

+    2,

+    0x39,

+    128,

+    CacheAssociativity4Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x3B,

+    128,

+    CacheAssociativity2Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x3C,

+    256,

+    CacheAssociativity4Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x41,

+    128,

+    CacheAssociativity4Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x42,

+    256,

+    CacheAssociativity4Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x43,

+    512,

+    CacheAssociativity4Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x44,

+    1024,

+    CacheAssociativity4Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x45,

+    2048,

+    CacheAssociativity4Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x49,

+    4096,

+    CacheAssociativity16Way,

+    CacheTypeUnified

+  },

+  {

+    1,

+    0x60,

+    16,

+    CacheAssociativity8Way,

+    CacheTypeData

+  },

+  {

+    1,

+    0x66,

+    8,

+    CacheAssociativity4Way,

+    CacheTypeData

+  },

+  {

+    1,

+    0x67,

+    16,

+    CacheAssociativity4Way,

+    CacheTypeData

+  },

+  {

+    1,

+    0x68,

+    32,

+    CacheAssociativity4Way,

+    CacheTypeData

+  },

+  {

+    2,

+    0x78,

+    1024,

+    CacheAssociativity4Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x79,

+    128,

+    CacheAssociativity8Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x7A,

+    256,

+    CacheAssociativity8Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x7B,

+    512,

+    CacheAssociativity8Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x7C,

+    1024,

+    CacheAssociativity8Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x7D,

+    2048,

+    CacheAssociativity8Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x7F,

+    512,

+    CacheAssociativity2Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x82,

+    256,

+    CacheAssociativity8Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x83,

+    512,

+    CacheAssociativity8Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x84,

+    1024,

+    CacheAssociativity8Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x85,

+    2048,

+    CacheAssociativity8Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x86,

+    512,

+    CacheAssociativity4Way,

+    CacheTypeUnified

+  },

+  {

+    2,

+    0x87,

+    1024,

+    CacheAssociativity8Way,

+    CacheTypeUnified

+  }

+};

+

+/**

+  Get cache data from CPUID EAX = 2.

+  

+  @param[in]    ProcessorNumber     Processor number of specified processor.

+  @param[out]   CacheData           Pointer to the cache data gotten from CPUID EAX = 2.

+

+**/

+VOID

+GetCacheDataFromCpuid2 (

+  IN UINTN              ProcessorNumber,

+  OUT CPU_CACHE_DATA    *CacheData

+  )

+{

+  UINT8                     CacheLevel;

+  EFI_CPUID_REGISTER        *CacheInformation;

+  UINTN                     CacheDescriptorNum;

+  UINT32                    RegPointer[4];

+  UINT8                     RegIndex;

+  UINT32                    RegValue;

+  UINT8                     ByteIndex;

+  UINT8                     Descriptor;

+  UINTN                     DescriptorIndex;

+

+  DEBUG ((EFI_D_INFO, "Get cache data from CPUID EAX = 2\n"));

+

+  CacheDescriptorNum = (UINTN) (sizeof (mCacheConverter) / sizeof (mCacheConverter[0]));

+  CacheInformation = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_CACHE_INFO);

+  ASSERT (CacheInformation != NULL);

+

+  CopyMem (RegPointer, CacheInformation, sizeof (EFI_CPUID_REGISTER));

+  RegPointer[0] &= 0xFFFFFF00;

+

+  for (RegIndex = 0; RegIndex < 4; RegIndex++) {

+    RegValue = RegPointer[RegIndex];

+    //

+    // The most significant bit (bit 31) of each register indicates whether the register

+    // contains valid information (set to 0) or is reserved (set to 1).

+    //

+    if ((RegValue & BIT31) != 0) {

+      continue;

+    }

+

+    for (ByteIndex = 0; ByteIndex < 4; ByteIndex++) {

+      Descriptor = (UINT8) ((RegValue >> (ByteIndex * 8)) & 0xFF);

+      for (DescriptorIndex = 0; DescriptorIndex < CacheDescriptorNum; DescriptorIndex++) {

+        if (mCacheConverter[DescriptorIndex].CacheDescriptor == Descriptor) {

+          CacheLevel = mCacheConverter[DescriptorIndex].CacheLevel; // 1 based

+          ASSERT (CacheLevel >= 1 && CacheLevel <= CPU_CACHE_LMAX);

+          CacheData[CacheLevel - 1].CacheSizeinKB = (UINT16) (CacheData[CacheLevel - 1].CacheSizeinKB + mCacheConverter[DescriptorIndex].CacheSizeinKB);

+          CacheData[CacheLevel - 1].SystemCacheType = mCacheConverter[DescriptorIndex].SystemCacheType;

+          CacheData[CacheLevel - 1].Associativity = mCacheConverter[DescriptorIndex].Associativity;

+        }

+      }   

+    }

+  }

+}

+

+/**

+  Get cache data from CPUID EAX = 4.

+

+  CPUID EAX = 4 is Deterministic Cache Parameters Leaf.

+  

+  @param[in]    ProcessorNumber     Processor number of specified processor.

+  @param[out]   CacheData           Pointer to the cache data gotten from CPUID EAX = 4.

+

+**/

+VOID

+GetCacheDataFromCpuid4 (

+  IN UINTN              ProcessorNumber,

+  OUT CPU_CACHE_DATA    *CacheData

+  )

+{

+  EFI_CPUID_REGISTER            *CpuidRegisters;

+  UINT8                         Index;

+  UINT8                         NumberOfDeterministicCacheParameters;

+  UINT32                        Ways;

+  UINT32                        Partitions;

+  UINT32                        LineSize;

+  UINT32                        Sets;

+  CACHE_TYPE_DATA               SystemCacheType;

+  CACHE_ASSOCIATIVITY_DATA      Associativity;

+  UINT8                         CacheLevel;

+

+  DEBUG ((EFI_D_INFO, "Get cache data from CPUID EAX = 4\n"));

+

+  NumberOfDeterministicCacheParameters = (UINT8) GetNumberOfCpuidLeafs (ProcessorNumber, DeterministicCacheParametersCpuidLeafs);

+

+  for (Index = 0; Index < NumberOfDeterministicCacheParameters; Index++) {

+    CpuidRegisters = GetDeterministicCacheParametersCpuidLeaf (ProcessorNumber, Index);

+

+    if ((CpuidRegisters->RegEax & CPU_CACHE_TYPE_MASK) == 0) {

+      //break;

+      continue;

+    }

+

+    switch (CpuidRegisters->RegEax & CPU_CACHE_TYPE_MASK) {

+      case 1:

+        SystemCacheType = CacheTypeData;

+        break;

+      case 2:

+        SystemCacheType = CacheTypeInstruction;

+        break;

+      case 3:

+        SystemCacheType = CacheTypeUnified;

+        break;

+      default:

+        SystemCacheType = CacheTypeUnknown;

+    }

+

+    Ways = ((CpuidRegisters->RegEbx & CPU_CACHE_WAYS_MASK) >> CPU_CACHE_WAYS_SHIFT) + 1;

+    Partitions = ((CpuidRegisters->RegEbx & CPU_CACHE_PARTITIONS_MASK) >> CPU_CACHE_PARTITIONS_SHIFT) + 1;

+    LineSize = (CpuidRegisters->RegEbx & CPU_CACHE_LINESIZE_MASK) + 1;

+    Sets = CpuidRegisters->RegEcx + 1;

+

+    switch (Ways) {

+      case 2:

+        Associativity = CacheAssociativity2Way;

+        break;

+      case 4:

+        Associativity = CacheAssociativity4Way;

+        break;

+      case 8:

+        Associativity = CacheAssociativity8Way;

+        break;

+      case 12:

+        Associativity = CacheAssociativity12Way;

+        break;

+      case 16:

+        Associativity = CacheAssociativity16Way;

+        break;

+      case 24:

+        Associativity = CacheAssociativity24Way;

+        break;

+      case 32:

+        Associativity = CacheAssociativity32Way;

+        break;

+      case 48:

+        Associativity = CacheAssociativity48Way;

+        break;

+      case 64:

+        Associativity = CacheAssociativity64Way;

+        break;

+      default:

+        Associativity = CacheAssociativityFully;

+        break;

+    }

+

+    CacheLevel = (UINT8) ((CpuidRegisters->RegEax & CPU_CACHE_LEVEL_MASK) >> CPU_CACHE_LEVEL_SHIFT); // 1 based

+    ASSERT (CacheLevel >= 1 && CacheLevel <= CPU_CACHE_LMAX);

+    CacheData[CacheLevel - 1].CacheSizeinKB = (UINT16) (CacheData[CacheLevel - 1].CacheSizeinKB + (Ways * Partitions * LineSize * Sets) / 1024);

+    CacheData[CacheLevel - 1].SystemCacheType = SystemCacheType;

+    CacheData[CacheLevel - 1].Associativity = Associativity;

+  }

+

+}

+

+/**

+  Add Type 7 SMBIOS Record for Cache Information.

+  

+  @param[in]    ProcessorNumber     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              ProcessorNumber,

+  OUT EFI_SMBIOS_HANDLE *L1CacheHandle,

+  OUT EFI_SMBIOS_HANDLE *L2CacheHandle,

+  OUT EFI_SMBIOS_HANDLE *L3CacheHandle

+  )

+{

+  EFI_STATUS                    Status;

+  SMBIOS_TABLE_TYPE7            *SmbiosRecord;

+  EFI_SMBIOS_HANDLE             SmbiosHandle;

+  UINT8                         CacheLevel;

+  CPU_CACHE_DATA                CacheData[CPU_CACHE_LMAX];

+  CHAR8                         *OptionalStrStart;

+  UINTN                         StringBufferSize;

+  UINTN                         CacheSocketStrLen;

+  EFI_STRING                    CacheSocketStr;

+  CACHE_SRAM_TYPE_DATA          CacheSramType;

+  CPU_CACHE_CONFIGURATION_DATA  CacheConfig;

+

+  ZeroMem (CacheData, CPU_CACHE_LMAX * sizeof (CPU_CACHE_DATA));

+

+  //

+  // Check whether the CPU supports CPUID EAX = 4, if yes, get cache data from CPUID EAX = 4,

+  // or no, get cache data from CPUID EAX = 2 to be compatible with the earlier CPU.

+  //

+  if (GetNumberOfCpuidLeafs (ProcessorNumber, BasicCpuidLeaf) > 4 ) {

+    GetCacheDataFromCpuid4 (ProcessorNumber, CacheData);

+  } else {

+    GetCacheDataFromCpuid2 (ProcessorNumber, CacheData);

+  }

+

+  //

+  // Now cache data has been ready.

+  //

+  for (CacheLevel = 0; CacheLevel < CPU_CACHE_LMAX; CacheLevel++) {

+    //

+    // NO smbios record for zero-sized cache.

+    //

+    if (CacheData[CacheLevel].CacheSizeinKB == 0) {

+      continue;

+    }

+

+    DEBUG ((

+      EFI_D_INFO,

+      "CacheData: CacheLevel = 0x%x CacheSizeinKB = 0x%xKB SystemCacheType = 0x%x Associativity = 0x%x\n",

+      CacheLevel + 1,

+      CacheData[CacheLevel].CacheSizeinKB,

+      CacheData[CacheLevel].SystemCacheType,

+      CacheData[CacheLevel].Associativity

+      ));

+

+

+    StringBufferSize = sizeof (CHAR16) * SMBIOS_STRING_MAX_LENGTH;

+    CacheSocketStr = AllocateZeroPool (StringBufferSize);

+    ASSERT (CacheSocketStr != NULL);

+    CacheSocketStrLen = UnicodeSPrint (CacheSocketStr, StringBufferSize, L"L%x-Cache", CacheLevel + 1);

+    ASSERT (CacheSocketStrLen <= SMBIOS_STRING_MAX_LENGTH);

+

+    //

+    // Report Cache Information to Type 7 SMBIOS Record.

+    //

+

+    SmbiosRecord = AllocatePool (sizeof (SMBIOS_TABLE_TYPE7) + CacheSocketStrLen + 1 + 1);

+    ASSERT (SmbiosRecord != NULL);

+    ZeroMem (SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE7) + CacheSocketStrLen + 1 + 1);

+

+    SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_CACHE_INFORMATION;

+    SmbiosRecord->Hdr.Length = (UINT8) sizeof (SMBIOS_TABLE_TYPE7);

+    //

+    // Make handle chosen by smbios protocol.add automatically.

+    //

+    SmbiosRecord->Hdr.Handle = 0;

+    //

+    // Socket will be the 1st optional string following the formatted structure.

+    //

+    SmbiosRecord->SocketDesignation = 1;

+

+    //

+    // Cache Level - 1 through 8, e.g. an L1 cache would use value 000b and an L3 cache would use 010b.

+    //

+    CacheConfig.Level = CacheLevel;

+    CacheConfig.Socketed = 0;           // Not Socketed

+    CacheConfig.Reserved2 = 0;

+    CacheConfig.Location = 0;           // Internal Cache

+    CacheConfig.Enable = 1;             // Cache enabled

+    CacheConfig.OperationalMode = 1;    // Write Back

+    CacheConfig.Reserved1 = 0;

+    CopyMem (&SmbiosRecord->CacheConfiguration, &CacheConfig, 2);

+    //

+    // Only 1K granularity assumed here.

+    //

+    SmbiosRecord->MaximumCacheSize = CacheData[CacheLevel].CacheSizeinKB;

+    SmbiosRecord->InstalledSize = CacheData[CacheLevel].CacheSizeinKB;

+

+    ZeroMem (&CacheSramType, sizeof (CACHE_SRAM_TYPE_DATA));

+    CacheSramType.Synchronous = 1;

+    CopyMem (&SmbiosRecord->SupportedSRAMType, &CacheSramType, 2);

+    CopyMem (&SmbiosRecord->CurrentSRAMType, &CacheSramType, 2);

+

+    SmbiosRecord->CacheSpeed = 0;

+    SmbiosRecord->ErrorCorrectionType = CacheErrorSingleBit;

+    SmbiosRecord->SystemCacheType = (UINT8) CacheData[CacheLevel].SystemCacheType;

+    SmbiosRecord->Associativity = (UINT8) CacheData[CacheLevel].Associativity;

+

+    OptionalStrStart = (CHAR8 *) (SmbiosRecord + 1);

+    UnicodeStrToAsciiStr (CacheSocketStr, OptionalStrStart);

+

+    // 

+    // Now we have got the full smbios record, call smbios protocol to add this record.

+    //

+    SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;

+    Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER*) SmbiosRecord);

+

+    //

+    // Record L1/L2/L3 Cache Smbios Handle, Type 4 SMBIOS Record needs it.

+    //

+    if (CacheLevel + 1 == CPU_CACHE_L1) {

+      *L1CacheHandle = SmbiosHandle;

+    } else if (CacheLevel + 1 == CPU_CACHE_L2) {

+      *L2CacheHandle = SmbiosHandle;

+    } else if (CacheLevel + 1 == CPU_CACHE_L3) {

+      *L3CacheHandle  = SmbiosHandle;

+    }

+    FreePool (SmbiosRecord);

+    FreePool (CacheSocketStr);

+    ASSERT_EFI_ERROR (Status);

+  } 

+}

+

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CpuSmbios.c b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CpuSmbios.c
new file mode 100644
index 0000000..193ab19
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/CpuSmbios.c
@@ -0,0 +1,126 @@
+/** @file

+  Code to log processor and cache subclass data to smbios record.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+**/

+

+#include "Processor.h"

+#include "Cache.h"

+

+EFI_SMBIOS_PROTOCOL     *mSmbios;

+EFI_HII_HANDLE          mStringHandle;

+UINT32                  mPopulatedSocketCount;

+

+/**

+  Add SMBIOS Processor Type and Cache Type tables for the CPU.

+**/

+VOID

+AddCpuSmbiosTables (

+  VOID

+  )

+{

+  EFI_STATUS            Status;

+  EFI_SMBIOS_HANDLE     L1CacheHandle;

+  EFI_SMBIOS_HANDLE     L2CacheHandle;

+  EFI_SMBIOS_HANDLE     L3CacheHandle;

+  UINT32                PreviousPackageNumber;

+  UINT32                PackageNumber;

+  UINTN                 ProcessorIndex;

+  UINTN                 *SocketProcessorNumberTable;

+  UINT32                SocketIndex;

+

+  L1CacheHandle = 0xFFFF;

+  L2CacheHandle = 0xFFFF;

+  L3CacheHandle = 0xFFFF;

+

+  //

+  // Initialize the mSmbios to contain the SMBIOS protocol,

+  //

+  Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **) &mSmbios);

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Initialize strings to HII database

+  //

+  mStringHandle = HiiAddPackages (

+                    &gEfiCallerIdGuid,

+                    NULL,

+                    CpuMpDxeStrings,

+                    NULL

+                    );

+  ASSERT (mStringHandle != NULL);

+

+  SocketProcessorNumberTable = AllocateZeroPool (mCpuConfigConextBuffer.NumberOfProcessors * sizeof (UINTN));

+  ASSERT (SocketProcessorNumberTable != NULL);

+

+  //

+  // Detect populated sockets (comparing the processors' PackangeNumber) and record their ProcessorNumber.

+  // For example:

+  //   ProcessorNumber: 0 1 2 3 (PackageNumber 0) 4 5 6 7 (PackageNumber 1)

+  //   And then, populated socket count will be 2 and record ProcessorNumber 0 for Socket 0, ProcessorNumber 4 for Socket 1

+  //

+

+  //

+  // System has 1 populated socket at least, initialize mPopulatedSocketCount to 1 and record ProcessorNumber 0 for it.

+  //

+  mPopulatedSocketCount = 1;

+  SocketProcessorNumberTable[0] = 0;

+  GetProcessorLocation (0, &PreviousPackageNumber, NULL, NULL);

+

+  //

+  // Scan and compare the processors' PackageNumber to find the populated sockets.

+  //

+  for (ProcessorIndex = 1; ProcessorIndex < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorIndex++) {

+    GetProcessorLocation (ProcessorIndex, &PackageNumber, NULL, NULL);

+    if (PackageNumber != PreviousPackageNumber) {

+      //

+      // Found a new populated socket.

+      //

+      PreviousPackageNumber = PackageNumber;

+      mPopulatedSocketCount++;

+      SocketProcessorNumberTable[mPopulatedSocketCount - 1] = ProcessorIndex;

+    }

+  }

+

+  //

+  // Add SMBIOS tables for populated sockets.

+  //

+  for (SocketIndex = 0; SocketIndex < mPopulatedSocketCount; SocketIndex++) {

+    AddSmbiosCacheTypeTable (SocketProcessorNumberTable[SocketIndex], &L1CacheHandle, &L2CacheHandle, &L3CacheHandle);

+    AddSmbiosProcessorTypeTable (SocketProcessorNumberTable[SocketIndex], L1CacheHandle, L2CacheHandle, L3CacheHandle);

+  }

+  FreePool (SocketProcessorNumberTable);

+

+  //

+  // Register notification functions for Smbios Processor Type.

+  //

+  SmbiosProcessorTypeTableCallback ();

+}

+

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Processor.h b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Processor.h
new file mode 100644
index 0000000..c517c3e
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/Processor.h
@@ -0,0 +1,172 @@
+/** @file

+  Include file for record processor subclass data with Smbios protocol.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+**/

+

+#ifndef _PROCESSOR_H_

+#define _PROCESSOR_H_

+

+#include "MpCommon.h"

+

+//

+// This is the string tool generated data representing our strings.

+//

+extern UINT8                    CpuMpDxeStrings[];

+extern EFI_SMBIOS_PROTOCOL      *mSmbios;

+extern EFI_HII_HANDLE           mStringHandle;

+extern UINT32                   mPopulatedSocketCount;

+

+//

+// This constant defines the maximum length of the CPU brand string. According to the

+// IA manual, the brand string is in EAX through EDX (thus 16 bytes) after executing

+// the CPUID instructions with EAX as 80000002, 80000003, 80000004.

+//

+#define MAXIMUM_CPU_BRAND_STRING_LENGTH 48

+

+typedef struct {

+  BOOLEAN           StringValid;

+  CHAR16            BrandString[MAXIMUM_CPU_BRAND_STRING_LENGTH + 1];

+  EFI_STRING_ID     StringRef;

+} CPU_PROCESSOR_VERSION_INFORMATION;

+

+//

+// It is defined for SMBIOS_TABLE_TYPE4.Status.

+//

+typedef struct {

+  UINT8 CpuStatus       :3; // Indicates the status of the processor.

+  UINT8 Reserved1       :3; // Reserved for future use. Should be set to zero.

+  UINT8 SocketPopulated :1; // Indicates if the processor socket is populated or not.

+  UINT8 Reserved2       :1; // Reserved for future use. Should be set to zero.

+} CPU_PROCESSOR_STATUS_DATA;

+

+//

+// It is defined for SMBIOS_TABLE_TYPE4.ProcessorCharacteristics.

+//

+typedef struct {

+  UINT16 Reserved       :1;

+  UINT16 Unknown        :1;

+  UINT16 Capable64Bit   :1;

+  UINT16 Reserved2      :13;

+} CPU_PROCESSOR_CHARACTERISTICS_DATA;

+

+/**

+  Add Processor Information to Type 4 SMBIOS Record for Socket Populated.

+

+  @param[in]    ProcessorNumber     Processor number of specified processor.

+  @param[in]    L1CacheHandle       The handle of the L1 Cache SMBIOS record.

+  @param[in]    L2CacheHandle       The handle of the L2 Cache SMBIOS record.

+  @param[in]    L3CacheHandle       The handle of the L3 Cache SMBIOS record.

+

+**/

+VOID

+AddSmbiosProcessorTypeTable (

+  IN UINTN              ProcessorNumber,

+  IN EFI_SMBIOS_HANDLE  L1CacheHandle,

+  IN EFI_SMBIOS_HANDLE  L2CacheHandle,

+  IN EFI_SMBIOS_HANDLE  L3CacheHandle

+  );

+

+/**

+  Register notification functions for Pcds related to Smbios Processor Type.

+**/

+VOID

+SmbiosProcessorTypeTableCallback (

+  VOID

+  );

+

+/**

+  Returns the processor voltage of the processor installed in the system.

+

+  @param    ProcessorNumber     Processor number of specified processor.

+

+  @return   Processor Voltage in mV

+

+**/

+UINT16

+GetProcessorVoltage (

+  IN UINTN  ProcessorNumber

+  );

+

+/**

+  Returns the procesor version string token installed in the system.

+

+  @param    ProcessorNumber  Processor number of specified processor.

+  @param    Version          Pointer to the output processor version.

+

+**/

+VOID

+GetProcessorVersion (

+  IN UINTN                                  ProcessorNumber,

+  OUT CPU_PROCESSOR_VERSION_INFORMATION     *Version

+  );

+

+/**

+  Returns the processor family of the processor installed in the system.

+

+  @param    ProcessorNumber     Processor number of specified processor.

+

+  @return   Processor Family

+

+**/

+PROCESSOR_FAMILY_DATA

+GetProcessorFamily (

+  IN UINTN  ProcessorNumber

+  );

+

+/**

+  Returns the procesor manufaturer string token installed in the system.

+

+  @param    ProcessorNumber     Processor number of specified processor.

+

+  @return   Processor Manufacturer string token.

+

+**/

+EFI_STRING_ID

+GetProcessorManufacturer (

+  IN UINTN  ProcessorNumber

+  );

+

+/**

+  Checks if processor is Intel or not.

+

+  @param    ProcessorNumber     Processor number of specified processor.

+

+  @return   TRUE                Intel Processor.

+  @return   FALSE               Not Intel Processor.

+

+**/

+BOOLEAN

+IsIntelProcessor (

+  IN UINTN  ProcessorNumber

+  );

+

+#endif

+

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorData.c b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorData.c
new file mode 100644
index 0000000..21cd45e
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorData.c
@@ -0,0 +1,203 @@
+/** @file

+  Code to retrieve processor sublcass data.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+**/

+

+#include "Cpu.h"

+#include "Processor.h"

+

+/**

+  Returns the procesor version string token installed in the system.

+

+  @param    ProcessorNumber  Processor number of specified processor.

+  @param    Version          Pointer to the output processor version.

+

+**/

+VOID

+GetProcessorVersion (

+  IN UINTN                                  ProcessorNumber,

+  OUT CPU_PROCESSOR_VERSION_INFORMATION     *Version

+  )

+{

+  CHAR16                BrandIdString[MAXIMUM_CPU_BRAND_STRING_LENGTH + 1];

+  EFI_CPUID_REGISTER    *CpuBrandString;

+  UINT8                 Index;

+

+  //

+  // Create the string using Brand ID String.

+  //

+  Version->StringValid = FALSE;

+

+  if (IsIntelProcessor (ProcessorNumber)) {

+    Version->StringRef = STRING_TOKEN (STR_INTEL_GENUINE_PROCESSOR);

+

+    CpuBrandString = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_BRAND_STRING1);

+    ASSERT (CpuBrandString != NULL);

+

+    //

+    // Check if Brand ID String is supported or filled up

+    //

+    if (CpuBrandString->RegEax != 0) {

+      AsciiStrToUnicodeStr ((CHAR8 *) CpuBrandString, (CHAR16 *) &BrandIdString[0]);

+

+      CpuBrandString = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_BRAND_STRING2);

+      ASSERT (CpuBrandString != NULL);

+      AsciiStrToUnicodeStr ((CHAR8 *) CpuBrandString, (CHAR16 *) &BrandIdString[16]);

+

+      CpuBrandString = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_BRAND_STRING3);

+      ASSERT (CpuBrandString != NULL);

+      AsciiStrToUnicodeStr ((CHAR8 *) CpuBrandString, (CHAR16 *) &BrandIdString[32]);

+

+      //

+      // Remove preceeding spaces

+      //

+      Index = 0;

+      while (((Index < MAXIMUM_CPU_BRAND_STRING_LENGTH) && (BrandIdString[Index] == 0x20)) != 0) {

+        Index++;

+      }

+

+      ASSERT (Index <= MAXIMUM_CPU_BRAND_STRING_LENGTH);

+      CopyMem (

+        Version->BrandString,

+        &BrandIdString[Index],

+        (MAXIMUM_CPU_BRAND_STRING_LENGTH - Index) * sizeof (CHAR16)

+        );

+      Version->BrandString[MAXIMUM_CPU_BRAND_STRING_LENGTH - Index] = 0;

+      Version->StringValid = TRUE;

+    }

+  } else {

+    Version->StringRef = STRING_TOKEN (STR_UNKNOWN);

+  }

+}

+

+/**

+  Returns the procesor manufaturer string token installed in the system.

+

+  @param    ProcessorNumber     Processor number of specified processor.

+

+  @return   Processor Manufacturer string token.

+

+**/

+EFI_STRING_ID

+GetProcessorManufacturer (

+  IN UINTN  ProcessorNumber

+  )

+{

+  if (IsIntelProcessor (ProcessorNumber)) {

+    return STRING_TOKEN (STR_INTEL_CORPORATION);

+  } else {

+    return STRING_TOKEN (STR_UNKNOWN);

+  }

+}

+

+/**

+  Checks if processor is Intel or not.

+

+  @param    ProcessorNumber     Processor number of specified processor.

+

+  @return   TRUE                Intel Processor.

+  @return   FALSE               Not Intel Processor.

+

+**/

+BOOLEAN

+IsIntelProcessor (

+  IN UINTN  ProcessorNumber

+  )

+{

+  EFI_CPUID_REGISTER  *Reg;

+

+  Reg = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_SIGNATURE);

+  ASSERT (Reg != NULL);

+

+  //

+  // After CPUID(0), check if EBX contians 'uneG', ECX contains 'letn', and EDX contains 'Ieni'

+  //

+  if ((Reg->RegEbx != 0x756e6547) || (Reg->RegEcx != 0x6c65746e) || (Reg->RegEdx != 0x49656e69)) {

+    return FALSE;

+  } else {

+    return TRUE;

+  }

+}

+

+/**

+  Returns the processor family of the processor installed in the system.

+

+  @param    ProcessorNumber     Processor number of specified processor.

+

+  @return   Processor Family

+

+**/

+PROCESSOR_FAMILY_DATA

+GetProcessorFamily (

+  IN UINTN  ProcessorNumber

+  )

+{

+  UINT32  FamilyId;

+  UINT32  ModelId;

+

+  if (IsIntelProcessor (ProcessorNumber)) {

+

+    GetProcessorVersionInfo (ProcessorNumber, &FamilyId, &ModelId, NULL, NULL);

+

+    return ProcessorFamilyPentium;

+  }

+

+  return ProcessorFamilyUnknown;

+}

+

+/**

+  Returns the processor voltage of the processor installed in the system.

+

+  @param    ProcessorNumber     Processor number of specified processor.

+

+  @return   Processor Voltage in mV

+

+**/

+UINT16

+GetProcessorVoltage (

+  IN UINTN  ProcessorNumber

+  )

+{

+  UINT16             VoltageInmV;

+  EFI_CPUID_REGISTER *Reg;

+

+  Reg = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_VERSION_INFO);

+  ASSERT (Reg != NULL);

+

+  if ((Reg->RegEax >> 8 & 0x3F) == 0xF) {

+    VoltageInmV = 3000;

+  } else {

+    VoltageInmV = 1600;

+  }

+

+  return VoltageInmV;

+}

+

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorSubClass.c b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorSubClass.c
new file mode 100644
index 0000000..9913647
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SMBIOS/ProcessorSubClass.c
@@ -0,0 +1,537 @@
+/** @file

+  Code to log processor subclass data with Smbios protocol.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+**/

+

+#include "Cpu.h"

+#include "Processor.h"

+

+UINTN mCpuSocketStrNumber = 1;

+UINTN mCpuAssetTagStrNumber = 4;

+

+/**

+  Add Type 4 SMBIOS Record for Socket Unpopulated.

+**/

+VOID

+AddUnpopulatedSmbiosProcessorTypeTable (

+  VOID

+  )

+{

+  EFI_STATUS            Status;

+  EFI_SMBIOS_HANDLE     SmbiosHandle;

+  UINTN                 TotalSize;

+  SMBIOS_TABLE_TYPE4    *SmbiosRecord;

+  CHAR8                 *OptionalStrStart;

+  EFI_STRING_ID         Token;

+  EFI_STRING            CpuSocketStr;

+  UINTN                 CpuSocketStrLen;

+

+  //

+  // Get CPU Socket string, it will be updated when PcdPlatformCpuSocketNames is set.

+  //

+  Token = STRING_TOKEN (STR_UNKNOWN);

+  CpuSocketStr = HiiGetPackageString (&gEfiCallerIdGuid, Token ,NULL);

+  ASSERT (CpuSocketStr != NULL);

+  CpuSocketStrLen = StrLen (CpuSocketStr);

+  ASSERT (CpuSocketStrLen <= SMBIOS_STRING_MAX_LENGTH);

+

+  //

+  // Report Processor Information to Type 4 SMBIOS Record.

+  //

+

+  TotalSize = sizeof (SMBIOS_TABLE_TYPE4) + CpuSocketStrLen + 1 + 1;

+  SmbiosRecord = AllocatePool (TotalSize);

+  ASSERT (SmbiosRecord != NULL);

+  ZeroMem (SmbiosRecord, TotalSize);

+

+  SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;

+  SmbiosRecord->Hdr.Length = (UINT8) sizeof (SMBIOS_TABLE_TYPE4);

+  //

+  // Make handle chosen by smbios protocol.add automatically.

+  //

+  SmbiosRecord->Hdr.Handle = 0;

+  //

+  // Socket will be the 1st optional string following the formatted structure.

+  //

+  SmbiosRecord->Socket = (UINT8) mCpuSocketStrNumber;

+  SmbiosRecord->ProcessorType = CentralProcessor;

+

+  //

+  // Just indicate CPU Socket Unpopulated.

+  // CPU_PROCESSOR_STATUS_DATA.SocketPopulated: 1- CPU Socket populated and 0 - CPU Socket Unpopulated

+  //

+  SmbiosRecord->Status = 0;

+

+  SmbiosRecord->MaxSpeed = (UINT16) PcdGet32 (PcdPlatformCpuMaxCoreFrequency);

+  SmbiosRecord->ProcessorUpgrade = ProcessorUpgradeSocketLGA775;

+

+  SmbiosRecord->L1CacheHandle = 0xFFFF;

+  SmbiosRecord->L2CacheHandle = 0xFFFF;

+  SmbiosRecord->L3CacheHandle = 0xFFFF;

+

+  OptionalStrStart = (CHAR8 *) (SmbiosRecord + 1);

+  UnicodeStrToAsciiStr (CpuSocketStr, OptionalStrStart);

+  //

+  // Now we have got the full smbios record, call smbios protocol to add this record.

+  //

+  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;

+  Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord);

+  FreePool (SmbiosRecord);

+  FreePool (CpuSocketStr);

+  ASSERT_EFI_ERROR (Status);

+}

+

+/**

+  Add Processor Information to Type 4 SMBIOS Record for Socket Populated.

+

+  @param[in]    ProcessorNumber     Processor number of specified processor.

+  @param[in]    L1CacheHandle       The handle of the L1 Cache SMBIOS record.

+  @param[in]    L2CacheHandle       The handle of the L2 Cache SMBIOS record.

+  @param[in]    L3CacheHandle       The handle of the L3 Cache SMBIOS record.

+

+**/

+VOID

+AddSmbiosProcessorTypeTable (

+  IN UINTN              ProcessorNumber,

+  IN EFI_SMBIOS_HANDLE  L1CacheHandle,

+  IN EFI_SMBIOS_HANDLE  L2CacheHandle,

+  IN EFI_SMBIOS_HANDLE  L3CacheHandle

+  )

+{

+  EFI_STATUS                    Status;

+  EFI_SMBIOS_HANDLE             SmbiosHandle;

+  UINTN                         TotalSize;

+  EFI_STRING_ID                 Token;

+  CHAR8                         *OptionalStrStart;

+  EFI_STRING                    CpuManuStr;

+  EFI_STRING                    CpuVerStr;

+  EFI_STRING                    CpuSocketStr;

+  EFI_STRING                    CpuAssetTagStr;

+  UINTN                         CpuManuStrLen;

+  UINTN                         CpuVerStrLen;

+  UINTN                         CpuSocketStrLen;

+  UINTN                         CpuAssetTagStrLen;

+  SMBIOS_TABLE_TYPE4            *SmbiosRecord;

+  EFI_CPUID_REGISTER            *CpuidRegister;

+  UINT16                        ProcessorVoltage;

+  CPU_PROCESSOR_VERSION_INFORMATION     Version;

+  CPU_PROCESSOR_STATUS_DATA     ProcessorStatus;

+  CPU_PROCESSOR_CHARACTERISTICS_DATA    ProcessorCharacteristics;

+  UINT16                        PackageThreadCount;

+  UINT16                        CoreThreadCount;

+  UINT8                         CoreCount;

+

+  CoreCount = 0;

+

+  //

+  // Get CPU Socket string, it will be updated when PcdPlatformCpuSocketNames is set.

+  //

+  Token = STRING_TOKEN (STR_UNKNOWN);

+  CpuSocketStr = HiiGetPackageString (&gEfiCallerIdGuid, Token ,NULL);

+  ASSERT (CpuSocketStr != NULL);

+  CpuSocketStrLen = StrLen (CpuSocketStr);

+  ASSERT (CpuSocketStrLen <= SMBIOS_STRING_MAX_LENGTH);

+

+  //

+  // Get CPU Manufacture string.

+  //

+  Token = GetProcessorManufacturer (ProcessorNumber);

+  CpuManuStr = HiiGetPackageString (&gEfiCallerIdGuid, Token, NULL);

+  ASSERT (CpuManuStr != NULL);

+  CpuManuStrLen = StrLen (CpuManuStr);

+  ASSERT (CpuManuStrLen <= SMBIOS_STRING_MAX_LENGTH);

+

+  //

+  // Get CPU Version string.

+  //

+  GetProcessorVersion (ProcessorNumber, &Version);

+  if (Version.StringValid) {

+    Token = HiiSetString (mStringHandle, 0, Version.BrandString, NULL);

+    if (Token == 0) {

+      Token = Version.StringRef;

+    }

+  } else {

+    Token = Version.StringRef;

+  }

+  CpuVerStr = HiiGetPackageString (&gEfiCallerIdGuid, Token, NULL);

+  ASSERT (CpuVerStr != NULL);

+  CpuVerStrLen = StrLen (CpuVerStr);

+  ASSERT (CpuVerStrLen <= SMBIOS_STRING_MAX_LENGTH);

+

+  //

+  // Get CPU Asset Tag string, it will be updated when PcdPlatformCpuAssetTags is set.

+  //

+  Token = STRING_TOKEN (STR_UNKNOWN);

+  CpuAssetTagStr = HiiGetPackageString (&gEfiCallerIdGuid, Token ,NULL);

+  ASSERT (CpuAssetTagStr != NULL);

+  CpuAssetTagStrLen = StrLen (CpuAssetTagStr);

+  ASSERT (CpuAssetTagStrLen <= SMBIOS_STRING_MAX_LENGTH);

+

+  //

+  // Get CPU core count.

+  //

+  if (GetNumberOfCpuidLeafs (ProcessorNumber, BasicCpuidLeaf) > EFI_CPUID_CORE_TOPOLOGY) {

+    CpuidRegister = GetExtendedTopologyEnumerationCpuidLeafs (ProcessorNumber, 1);

+    PackageThreadCount = (UINT16) (CpuidRegister->RegEbx);

+    CpuidRegister = GetExtendedTopologyEnumerationCpuidLeafs (ProcessorNumber, 0);

+    CoreThreadCount = (UINT16) (CpuidRegister->RegEbx);

+    CoreCount = (UINT8) (PackageThreadCount / CoreThreadCount);

+  }

+

+  //

+  // Report Processor Information to Type 4 SMBIOS Record.

+  //

+

+  TotalSize = sizeof (SMBIOS_TABLE_TYPE4) + CpuSocketStrLen + 1 + CpuManuStrLen + 1 + CpuVerStrLen + 1 + CpuAssetTagStrLen + 1 + 1;

+  SmbiosRecord = AllocatePool (TotalSize);

+  ASSERT (SmbiosRecord != NULL);

+  ZeroMem (SmbiosRecord, TotalSize);

+

+  SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;

+  SmbiosRecord->Hdr.Length = (UINT8) sizeof (SMBIOS_TABLE_TYPE4);

+  //

+  // Make handle chosen by smbios protocol.add automatically.

+  //

+  SmbiosRecord->Hdr.Handle = 0;

+  //

+  // Socket will be the 1st optional string following the formatted structure.

+  //

+  SmbiosRecord->Socket = (UINT8) mCpuSocketStrNumber;

+  SmbiosRecord->ProcessorType = CentralProcessor;

+  SmbiosRecord->ProcessorFamily = (UINT8) GetProcessorFamily (ProcessorNumber); 

+  //

+  // Manu will be the 2nd optional string following the formatted structure.

+  //

+  SmbiosRecord->ProcessorManufacture = 2;   

+

+  CpuidRegister = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_VERSION_INFO);

+  ASSERT (CpuidRegister != NULL);

+  *(UINT32 *) &SmbiosRecord->ProcessorId.Signature = CpuidRegister->RegEax;

+  *(UINT32 *) &SmbiosRecord->ProcessorId.FeatureFlags = CpuidRegister->RegEdx,

+

+  //

+  // Version will be the 3rd optional string following the formatted structure.

+  // 

+  SmbiosRecord->ProcessorVersion = 3;   

+

+  ProcessorVoltage = GetProcessorVoltage (ProcessorNumber); // mV unit

+  ProcessorVoltage = (UINT16) ((ProcessorVoltage * 10) / 1000);

+  *(UINT8 *) &SmbiosRecord->Voltage = (UINT8) ProcessorVoltage;

+  SmbiosRecord->Voltage.ProcessorVoltageIndicateLegacy = 1;

+

+  SmbiosRecord->ExternalClock = (UINT16) (GET_CPU_MISC_DATA (ProcessorNumber, IntendedFsbFrequency));

+  SmbiosRecord->MaxSpeed = (UINT16) PcdGet32 (PcdPlatformCpuMaxCoreFrequency);

+  SmbiosRecord->CurrentSpeed = (UINT16) (GET_CPU_MISC_DATA (ProcessorNumber, IntendedFsbFrequency) * GET_CPU_MISC_DATA (ProcessorNumber, MaxCoreToBusRatio));

+

+  ProcessorStatus.CpuStatus = 1;        // CPU Enabled

+  ProcessorStatus.Reserved1 = 0;

+  ProcessorStatus.SocketPopulated = 1;  // CPU Socket Populated

+  ProcessorStatus.Reserved2 = 0;

+  CopyMem (&SmbiosRecord->Status, &ProcessorStatus, 1);

+

+  SmbiosRecord->ProcessorUpgrade = ProcessorUpgradeSocketLGA775;

+

+  SmbiosRecord->L1CacheHandle = L1CacheHandle;

+  SmbiosRecord->L2CacheHandle = L2CacheHandle;

+  SmbiosRecord->L3CacheHandle = L3CacheHandle;

+

+  //

+  // AssetTag will be the 4th optional string following the formatted structure.

+  //

+  SmbiosRecord->AssetTag = (UINT8) mCpuAssetTagStrNumber;

+

+  SmbiosRecord->CoreCount = CoreCount;

+

+  ProcessorCharacteristics.Reserved = 0;

+  ProcessorCharacteristics.Capable64Bit = 1; // 64-bit Capable

+  ProcessorCharacteristics.Unknown = 0;

+  ProcessorCharacteristics.Reserved2 = 0;

+  CopyMem (&SmbiosRecord->ProcessorCharacteristics, &ProcessorCharacteristics, 2);

+

+  OptionalStrStart = (CHAR8 *) (SmbiosRecord + 1);

+  UnicodeStrToAsciiStr (CpuSocketStr, OptionalStrStart);

+  UnicodeStrToAsciiStr (CpuManuStr, OptionalStrStart + CpuSocketStrLen + 1);

+  UnicodeStrToAsciiStr (CpuVerStr, OptionalStrStart + CpuSocketStrLen + 1 + CpuManuStrLen + 1);

+  UnicodeStrToAsciiStr (CpuAssetTagStr, OptionalStrStart + CpuSocketStrLen + 1 + CpuManuStrLen + 1 + CpuVerStrLen + 1);

+  //

+  // Now we have got the full smbios record, call smbios protocol to add this record.

+  //

+  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;

+  Status = mSmbios->Add (mSmbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord);

+  FreePool (SmbiosRecord);

+  FreePool (CpuSocketStr);

+  FreePool (CpuManuStr);

+  FreePool (CpuVerStr);

+  FreePool (CpuAssetTagStr);

+  ASSERT_EFI_ERROR (Status);

+}

+

+/**

+  Get Type 4 SMBIOS Record table.

+

+  @param[in, out]   SmbiosHandle    On entry, points to the previous handle of the SMBIOS record. On exit, points to the

+                                    next SMBIOS record handle. If it is zero on entry, then the first SMBIOS record

+                                    handle will be returned. If it returns zero on exit, then there are no more SMBIOS records.

+  @param[out]       Record          Returned pointer to record buffer .

+

+**/

+VOID

+GetSmbiosProcessorTypeTable (

+  IN OUT EFI_SMBIOS_HANDLE      *SmbiosHandle,

+  OUT EFI_SMBIOS_TABLE_HEADER   *Record OPTIONAL

+  )

+{

+  EFI_STATUS                 Status;

+  EFI_SMBIOS_TYPE            RecordType;

+  EFI_SMBIOS_TABLE_HEADER    *Buffer;

+

+  RecordType = EFI_SMBIOS_TYPE_PROCESSOR_INFORMATION;

+  do {

+    Status = mSmbios->GetNext (

+                        mSmbios,

+                        SmbiosHandle,

+                        &RecordType,

+                        &Buffer, 

+                        NULL

+                        );

+    if (!EFI_ERROR(Status)) {

+      if (Record != NULL) {

+        Record = Buffer;

+      }

+      return;

+    }

+  } while (!EFI_ERROR(Status));

+

+}

+

+/**

+  Notification function when PcdPlatformCpuSocketCount is set.

+

+  @param[in]        CallBackGuid    The PCD token GUID being set.

+  @param[in]        CallBackToken   The PCD token number being set.

+  @param[in, out]   TokenData       A pointer to the token data being set.

+  @param[in]        TokenDataSize   The size, in bytes, of the data being set.

+

+**/

+VOID

+EFIAPI

+CallbackOnPcdPlatformCpuSocketCount (

+  IN        CONST GUID      *CallBackGuid, OPTIONAL

+  IN        UINTN           CallBackToken,

+  IN  OUT   VOID            *TokenData,

+  IN        UINTN           TokenDataSize

+  )

+{

+  UINT32 CpuSocketCount;

+  UINT32 SocketIndex;

+

+  CpuSocketCount = 0;

+  if (CallBackToken == PcdToken (PcdPlatformCpuSocketCount)) {

+    if (TokenDataSize == sizeof (UINT32)) {

+      CpuSocketCount = ReadUnaligned32 (TokenData);

+    }

+  }

+

+  DEBUG ((EFI_D_INFO, "Callback: PcdPlatformCpuSocketCount is set\n"));

+

+  if (CpuSocketCount <= mPopulatedSocketCount) {

+    return;

+  }

+

+  //

+  // Add Type 4 SMBIOS Record for Socket Unpopulated.

+  //

+  for (SocketIndex = mPopulatedSocketCount; SocketIndex < CpuSocketCount; SocketIndex++) {

+    AddUnpopulatedSmbiosProcessorTypeTable ();

+  }

+

+}

+

+/**

+  Notification function when PcdPlatformCpuSocketNames is set.

+

+  @param[in]        CallBackGuid    The PCD token GUID being set.

+  @param[in]        CallBackToken   The PCD token number being set.

+  @param[in, out]   TokenData       A pointer to the token data being set.

+  @param[in]        TokenDataSize   The size, in bytes, of the data being set.

+

+**/

+VOID

+EFIAPI

+CallbackOnPcdPlatformCpuSocketNames (

+  IN        CONST GUID      *CallBackGuid, OPTIONAL

+  IN        UINTN           CallBackToken,

+  IN  OUT   VOID            *TokenData,

+  IN        UINTN           TokenDataSize

+  )

+{

+  CHAR16            **CpuSocketNames;

+  CHAR8             *CpuSocketStr;

+  UINTN             CpuSocketStrLen;

+  UINT32            SocketIndex;

+  EFI_SMBIOS_HANDLE SmbiosHandle;

+  UINT32            CpuSocketCount;

+

+  CpuSocketNames = NULL;

+  if (CallBackToken == PcdToken (PcdPlatformCpuSocketNames)) {

+    if (TokenDataSize == sizeof (UINT64)) {

+      CpuSocketNames = (CHAR16 **) (UINTN) ReadUnaligned64 (TokenData);

+    }

+  }

+

+  DEBUG ((EFI_D_INFO, "Callback: PcdPlatformCpuSocketNames is set\n"));

+

+  if (CpuSocketNames == NULL) {

+    return;

+  }

+

+  CpuSocketCount = PcdGet32 (PcdPlatformCpuSocketCount);

+  if (CpuSocketCount < mPopulatedSocketCount) {

+    CpuSocketCount = mPopulatedSocketCount;

+  }

+

+  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;

+  SocketIndex = 0;

+

+  //

+  // Update CPU Socket string for Socket Populated.

+  //

+  do {

+    GetSmbiosProcessorTypeTable (&SmbiosHandle, NULL);

+    if (SmbiosHandle == SMBIOS_HANDLE_PI_RESERVED) {

+      return;

+    }

+    CpuSocketStrLen = StrLen (CpuSocketNames[SocketIndex]);

+    ASSERT (CpuSocketStrLen <= SMBIOS_STRING_MAX_LENGTH);

+    CpuSocketStr = AllocatePool (CpuSocketStrLen + 1);

+    UnicodeStrToAsciiStr (CpuSocketNames[SocketIndex], CpuSocketStr);

+    mSmbios->UpdateString (mSmbios, &SmbiosHandle, &mCpuSocketStrNumber, CpuSocketStr);

+    FreePool (CpuSocketStr);

+  } while ((++SocketIndex) < CpuSocketCount);

+

+}

+

+/**

+  Notification function when PcdPlatformCpuAssetTags is set.

+

+  @param[in]        CallBackGuid    The PCD token GUID being set.

+  @param[in]        CallBackToken   The PCD token number being set.

+  @param[in, out]   TokenData       A pointer to the token data being set.

+  @param[in]        TokenDataSize   The size, in bytes, of the data being set.

+

+**/

+VOID

+EFIAPI

+CallbackOnPcdPlatformCpuAssetTags (

+  IN        CONST GUID      *CallBackGuid, OPTIONAL

+  IN        UINTN           CallBackToken,

+  IN  OUT   VOID            *TokenData,

+  IN        UINTN           TokenDataSize

+  )

+{

+  CHAR16            **CpuAssetTags;

+  CHAR8             *CpuAssetTagStr;

+  UINTN             CpuAssetTagStrLen;

+  UINT32            SocketIndex;

+  EFI_SMBIOS_HANDLE SmbiosHandle;

+

+  CpuAssetTags = NULL;

+  if (CallBackToken == PcdToken (PcdPlatformCpuAssetTags)) {

+    if (TokenDataSize == sizeof (UINT64)) {

+      CpuAssetTags = (CHAR16 **) (UINTN) ReadUnaligned64 (TokenData);

+    }

+  }

+

+  DEBUG ((EFI_D_INFO, "Callback: PcdPlatformCpuAssetTags is set\n"));

+

+  if (CpuAssetTags == NULL) {

+    return;

+  }

+

+  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;

+  SocketIndex = 0;

+

+  //

+  // Update CPU Asset Tag string for Socket Populated.

+  //

+  do {

+    GetSmbiosProcessorTypeTable (&SmbiosHandle, NULL);

+    if (SmbiosHandle == SMBIOS_HANDLE_PI_RESERVED) {

+      return;

+    }

+    CpuAssetTagStrLen = StrLen (CpuAssetTags[SocketIndex]);

+    ASSERT (CpuAssetTagStrLen <= SMBIOS_STRING_MAX_LENGTH);

+    CpuAssetTagStr = AllocatePool (CpuAssetTagStrLen + 1);

+    UnicodeStrToAsciiStr (CpuAssetTags[SocketIndex], CpuAssetTagStr);

+    mSmbios->UpdateString (mSmbios, &SmbiosHandle, &mCpuAssetTagStrNumber, CpuAssetTagStr);

+    FreePool (CpuAssetTagStr);

+  } while ((++SocketIndex) < mPopulatedSocketCount);

+

+}

+

+/**

+  Register notification functions for Pcds related to Smbios Processor Type.

+**/

+VOID

+SmbiosProcessorTypeTableCallback (

+  VOID

+  )

+{

+  UINT32 CpuSocketCount;

+  UINT64 CpuSocketNames;

+  UINT64 CpuAssetTags;

+

+  CpuSocketCount = PcdGet32 (PcdPlatformCpuSocketCount);

+  CpuSocketNames = PcdGet64 (PcdPlatformCpuSocketNames);

+  CpuAssetTags = PcdGet64 (PcdPlatformCpuAssetTags);

+

+  //

+  // PcdPlatformCpuSocketCount, PcdPlatformCpuSocketNames and PcdPlatformCpuAssetTags

+  // have default value 0 in *.dec, check whether they have been set with valid value,

+  // if yes, process them directly, or no, register notification functions for them. 

+  //

+  if (CpuSocketCount <= mPopulatedSocketCount) {

+    LibPcdCallbackOnSet (NULL, PcdToken (PcdPlatformCpuSocketCount), CallbackOnPcdPlatformCpuSocketCount);

+  } else {

+    CallbackOnPcdPlatformCpuSocketCount (NULL, PcdToken (PcdPlatformCpuSocketCount), &CpuSocketCount, sizeof (UINT32));

+  }

+  if (CpuSocketNames == 0) {

+    LibPcdCallbackOnSet (NULL, PcdToken (PcdPlatformCpuSocketNames), CallbackOnPcdPlatformCpuSocketNames);

+  } else {

+    CallbackOnPcdPlatformCpuSocketNames (NULL, PcdToken (PcdPlatformCpuSocketNames), &CpuSocketNames, sizeof (UINT64));

+  }

+  if (CpuAssetTags == 0) {

+    LibPcdCallbackOnSet (NULL, PcdToken (PcdPlatformCpuAssetTags), CallbackOnPcdPlatformCpuAssetTags);

+  } else {

+    CallbackOnPcdPlatformCpuAssetTags (NULL, PcdToken (PcdPlatformCpuAssetTags), &CpuAssetTags, sizeof (UINT64));

+  }

+}

+

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/SelectLfp.c b/IA32FamilyCpuBasePkg/CpuMpDxe/SelectLfp.c
new file mode 100755
index 0000000..29a345b
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/SelectLfp.c
@@ -0,0 +1,221 @@
+/** @file

+

+  Code for Selecting Least-Feature Processor as BSP

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  SelectLfp.c

+

+**/

+

+#include "MpService.h"

+#include "Cpu.h"

+

+//

+// Common set of processors' feature flags.

+//

+UINT32    CommonFeatureFlagSet[6];

+//

+// Flags of whether corresponding processor matches common set.

+//

+BOOLEAN   MatchingCommonSet[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];

+

+/**

+  Get the common set of processors' feature flags.

+  

+  This function calculates the common set of processors' feature flags.

+  Processor's feature flags include 6 segments: CPUID(1).ECX, CPUID(1).EDX,

+  CPUID(0x80000001).EAX, CPUID(0x80000001).EBX, CPUID(0x80000001).ECX, 

+  and CPUID(0x80000001).EDX. "AND" them together and result is the common set.

+

+**/

+VOID

+GetCommonFeatureFlagSet (

+  VOID

+  )

+{

+  EFI_CPUID_REGISTER  *CpuidRegisters;

+  UINTN               ProcessorNumber;

+

+  //

+  // Initialize common set of feature flag with all "1"s.

+  //

+  SetMem32 (CommonFeatureFlagSet, sizeof (CommonFeatureFlagSet), 0xffffffff);

+

+  //

+  // Traverse all processors' feature flags

+  //

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+

+    //

+    // AND CPUID(1).ECX and CPUID(1).EDX with common set

+    //

+    CpuidRegisters = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_VERSION_INFO);

+    ASSERT (CpuidRegisters != NULL);

+    CommonFeatureFlagSet[0] &= CpuidRegisters->RegEcx;

+    CommonFeatureFlagSet[1] &= CpuidRegisters->RegEdx;

+

+    //

+    // AND CPUID(0x80000001).EAX, CPUID(0x80000001).EBX, CPUID(0x80000001).ECX,

+    // and CPUID(0x80000001).EDX with common set.

+    //

+    CpuidRegisters = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_EXTENDED_CPU_SIG);

+    ASSERT (CpuidRegisters != NULL);

+    CommonFeatureFlagSet[2] &= CpuidRegisters->RegEax;

+    CommonFeatureFlagSet[3] &= CpuidRegisters->RegEbx;

+    CommonFeatureFlagSet[4] &= CpuidRegisters->RegEcx;

+    CommonFeatureFlagSet[5] &= CpuidRegisters->RegEdx;

+  }

+}

+

+/**

+  Checks which processors match the common set of feature flag

+  

+  This function Checks which processors match the common set of feature flag.

+

+  @retval TRUE    At least one processor matches the common set of feature flag.

+  @retval FALSE   No processor matches the common set of feature flag.

+

+**/

+BOOLEAN

+CompareProcessorsWithCommonSet (

+  VOID

+  )

+{

+  EFI_CPUID_REGISTER  *CpuidRegisters;

+  UINTN               ProcessorNumber;

+  BOOLEAN             ReturnValue;

+

+  ReturnValue = FALSE;

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+    MatchingCommonSet[ProcessorNumber] = FALSE;

+    

+    //

+    // Compare CPUID(1).ECX and CPUID(1).EDX with common set

+    // 

+    CpuidRegisters = GetProcessorCpuid (0, EFI_CPUID_VERSION_INFO);

+    ASSERT (CpuidRegisters != NULL);

+    if (CommonFeatureFlagSet[0] != CpuidRegisters->RegEcx || CommonFeatureFlagSet[1] != CpuidRegisters->RegEdx) {

+      continue;

+    }

+

+    //

+    // Compare CPUID(0x80000001).EAX, CPUID(0x80000001).EBX, CPUID(0x80000001).ECX,

+    // and CPUID(0x80000001).EDX with common set.

+    //

+    CpuidRegisters = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_EXTENDED_CPU_SIG);

+    ASSERT (CpuidRegisters != NULL);

+    if (CommonFeatureFlagSet[2] != CpuidRegisters->RegEax || CommonFeatureFlagSet[3] != CpuidRegisters->RegEbx ||

+        CommonFeatureFlagSet[4] != CpuidRegisters->RegEcx || CommonFeatureFlagSet[5] != CpuidRegisters->RegEdx) {

+      continue;

+    }

+

+    //

+    // If the processor matches common set, flag it, and set return value as TRUE.

+    //

+    MatchingCommonSet[ProcessorNumber] = TRUE;

+    ReturnValue = TRUE;

+  }

+

+  return ReturnValue;

+}

+

+/**

+  Select least-feature processor as BSP

+  

+  This function selects least-feature processor as BSP.

+

+**/

+VOID

+SelectLfpAsBsp (

+  VOID

+  )

+{

+  UINTN               ProcessorNumber;

+  UINTN               OldestProcessorNumber;

+  UINT32              OldestProcessorFms[3];

+  UINT32              FamilyId;

+  UINT32              ModelId;

+  UINT32              SteppingId;

+  BOOLEAN             MatchingProcessorExist;

+

+  //

+  // Calculate the common set of processors' feature flags

+  //

+  GetCommonFeatureFlagSet ();

+

+  //

+  // Compare all logical processors with common set.

+  //

+  MatchingProcessorExist = CompareProcessorsWithCommonSet ();

+

+  OldestProcessorFms[2] = 0xffffffff;

+  OldestProcessorFms[1] = 0;

+  OldestProcessorFms[0] = 0;

+  OldestProcessorNumber = mCpuConfigConextBuffer.BspNumber;

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+

+    //

+    // If only 1 processor matches common set, it should be BSP

+    // If more than 1 processors match common set, the one with lowest CPUID should be BSP.

+    // If no processor matches common set, the processor with lowest CPUID should be BSP.

+    //

+    if (!MatchingProcessorExist || MatchingCommonSet[ProcessorNumber]) {

+      GetProcessorVersionInfo (ProcessorNumber, &FamilyId, &ModelId, &SteppingId, NULL);

+

+      if (FamilyId > OldestProcessorFms[2]) {

+        continue;

+      }

+

+      if (FamilyId == OldestProcessorFms[2]) {

+        if (ModelId > OldestProcessorFms[1]) {

+          continue;

+        }

+        if (ModelId == OldestProcessorFms[1]) {

+          if (SteppingId >= OldestProcessorFms[0]) {

+            continue;

+          }

+        }

+      }

+

+      OldestProcessorFms[2] = FamilyId;

+      OldestProcessorFms[1] = ModelId;

+      OldestProcessorFms[0] = SteppingId;

+      OldestProcessorNumber = ProcessorNumber;

+    }

+  }

+

+  //

+  // If current BSP is not the least-feature processor, then switch BSP.

+  //

+  if (OldestProcessorNumber != mCpuConfigConextBuffer.BspNumber) {

+    SwitchBSP (&mMpService, OldestProcessorNumber, TRUE);

+    DEBUG ((EFI_D_INFO, "BSP switched to processor: %8d\r\n", OldestProcessorNumber));

+  }

+}

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Setting.c b/IA32FamilyCpuBasePkg/CpuMpDxe/Setting.c
new file mode 100644
index 0000000..20b3141
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Setting.c
@@ -0,0 +1,351 @@
+/** @file

+  Code for Setting phase.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  Setting.c

+

+**/

+

+#include "Cpu.h"

+#include "MpService.h"

+#include "CpuOnlyReset.h"

+

+BOOLEAN    mRestoreSettingAfterInit = FALSE;

+BOOLEAN    mSetBeforeCpuOnlyReset;

+

+/**

+  Programs registers for the calling processor.

+

+  This function programs registers for the calling processor.

+

+  @param  PreSmmInit         Specify the target register table.

+                             If TRUE, the target is the pre-SMM-init register table.

+                             If FALSE, the target is the post-SMM-init register table.

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+SetProcessorRegisterEx (

+  IN BOOLEAN  PreSmmInit,

+  IN UINTN    ProcessorNumber

+  )

+{

+  CPU_REGISTER_TABLE        *RegisterTable;

+  CPU_REGISTER_TABLE_ENTRY  *RegisterTableEntry;

+  UINTN                     Index;

+  UINTN                     Value;

+  UINTN                     StartIndex;

+  UINTN                     EndIndex;

+

+  if (PreSmmInit) {

+    RegisterTable = &mCpuConfigConextBuffer.PreSmmInitRegisterTable[ProcessorNumber];

+  } else {

+    RegisterTable = &mCpuConfigConextBuffer.RegisterTable[ProcessorNumber];

+  }

+  

+  //

+  // If microcode patch has been applied, then the first register table entry

+  // is for microcode upate, so it is skipped.  

+  //

+  StartIndex = 0;

+

+  if (mSetBeforeCpuOnlyReset) {

+    EndIndex    = StartIndex + RegisterTable->NumberBeforeReset;

+  } else {

+    StartIndex += RegisterTable->NumberBeforeReset;

+    EndIndex    = RegisterTable->TableLength;

+  }

+

+  //

+  // Traverse Register Table of this logical processor

+  //

+  for (Index = StartIndex; Index < EndIndex; Index++) {

+

+    RegisterTableEntry = &RegisterTable->RegisterTableEntry[Index];

+    

+    //

+    // Check the type of specified register

+    //

+    switch (RegisterTableEntry->RegisterType) {

+    //

+    // The specified register is Control Register

+    //

+    case ControlRegister:

+      switch (RegisterTableEntry->Index) {

+      case 0:

+        Value = AsmReadCr0 ();

+        Value = (UINTN) BitFieldWrite64 (

+                          Value,

+                          RegisterTableEntry->ValidBitStart,

+                          RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,

+                          RegisterTableEntry->Value

+                          );

+        AsmWriteCr0 (Value);

+        break;

+      case 2:

+        Value = AsmReadCr2 ();

+        Value = (UINTN) BitFieldWrite64 (

+                          Value,

+                          RegisterTableEntry->ValidBitStart,

+                          RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,

+                          RegisterTableEntry->Value

+                          );

+        AsmWriteCr2 (Value);

+        break;

+      case 3:

+        Value = AsmReadCr3 ();

+        Value = (UINTN) BitFieldWrite64 (

+                          Value,

+                          RegisterTableEntry->ValidBitStart,

+                          RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,

+                          RegisterTableEntry->Value

+                          );

+        AsmWriteCr3 (Value);

+        break;

+      case 4:

+        Value = AsmReadCr4 ();

+        Value = (UINTN) BitFieldWrite64 (

+                          Value,

+                          RegisterTableEntry->ValidBitStart,

+                          RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,

+                          RegisterTableEntry->Value

+                          );

+        AsmWriteCr4 (Value);

+        break;

+      case 8:

+        //

+        //  Do we need to support CR8?

+        //

+        break;

+      default:

+        break;

+      }

+      break;

+    //

+    // The specified register is Model Specific Register

+    //

+    case Msr:

+      //

+      // If this function is called to restore register setting after INIT signal,

+      // there is no need to restore MSRs in register table.

+      //

+      if (!mRestoreSettingAfterInit) {

+        if (RegisterTableEntry->ValidBitLength >= 64) {

+          //

+          // If length is not less than 64 bits, then directly write without reading

+          //

+          AsmWriteMsr64 (

+            RegisterTableEntry->Index,

+            RegisterTableEntry->Value

+            );

+        } else {

+          //

+          // Set the bit section according to bit start and length

+          //

+          AsmMsrBitFieldWrite64 (

+            RegisterTableEntry->Index,

+            RegisterTableEntry->ValidBitStart,

+            RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,

+            RegisterTableEntry->Value

+            );

+        }

+      }

+      break;

+    //

+    // Enable or disable cache

+    //

+    case CacheControl:

+      //

+      // If value of the entry is 0, then disable cache.  Otherwise, enable cache.

+      //

+      if (RegisterTableEntry->Value == 0) {

+        AsmDisableCache ();

+      } else {

+        AsmEnableCache ();

+      }

+      break;

+

+    default:

+      break;

+    }

+  }

+}

+

+/**

+  Programs registers after SMM initialization for the calling processor.

+

+  This function programs registers after SMM initialization for the calling processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+SetProcessorRegister (

+  IN UINTN  ProcessorNumber

+  )

+{

+  SetProcessorRegisterEx (FALSE, ProcessorNumber);

+}

+

+/**

+  Programs registers before SMM initialization for the calling processor.

+

+  This function programs registers before SMM initialization for the calling processor.

+

+  @param  ProcessorNumber    Handle number of specified logical processor.

+

+**/

+VOID

+SetPreSmmInitProcessorRegister (

+  IN UINTN  ProcessorNumber

+  )

+{

+  SetProcessorRegisterEx (TRUE, ProcessorNumber);

+}

+

+/**

+  Triggers CPU-only reset and restores processor environment.

+

+  This function triggers CPU-only reset and restores processor environment.

+

+**/

+VOID

+CpuOnlyResetAndRestore (

+  VOID

+  )

+{

+  MTRR_SETTINGS  MtrrSetting;

+

+  MtrrGetAllMtrrs (&MtrrSetting);

+

+  InitiateCpuOnlyReset ();

+

+  DispatchAPAndWait (

+    TRUE,

+    0,

+    EarlyMpInit

+    );

+

+  EarlyMpInit (mCpuConfigConextBuffer.BspNumber);

+

+  ProgramVirtualWireMode ();

+}

+

+/**

+  Programs processor registers according to register tables.

+

+  This function programs processor registers according to register tables.

+

+**/

+VOID

+SettingPhase (

+  VOID

+  )

+{

+  UINT8                     CallbackSignalValue;

+  UINTN                     Index;

+  UINTN                     ProcessorNumber;

+  CPU_REGISTER_TABLE        *RegisterTable;

+  BOOLEAN                   NeedCpuOnlyReset;

+

+  //

+  // Set PcdCpuCallbackSignal to trigger callback function, and reads the value back.

+  //

+  CallbackSignalValue = SetAndReadCpuCallbackSignal (CPU_PROCESSOR_SETTING_SIGNAL);

+  //

+  // Checks whether the callback function requests to bypass Setting phase.

+  //

+  if (CallbackSignalValue == CPU_BYPASS_SIGNAL) {

+    return;

+  }

+

+  //

+  // Check if CPU-only reset is needed

+  //

+  NeedCpuOnlyReset = FALSE;

+  for (Index = 0; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) {

+    RegisterTable = &mCpuConfigConextBuffer.RegisterTable[Index];

+    if (RegisterTable->NumberBeforeReset > 0) {

+      NeedCpuOnlyReset = TRUE;

+      break;

+    }

+  }

+

+  //

+  // if CPU-only reset is needed, then program corresponding registers, and

+  // trigger CPU-only reset.

+  //

+  if (NeedCpuOnlyReset) {

+    mSetBeforeCpuOnlyReset = TRUE;

+    DispatchAPAndWait (

+      TRUE,

+      0,

+      SetProcessorRegister

+      );

+

+    SetProcessorRegister (mCpuConfigConextBuffer.BspNumber);

+

+    CpuOnlyResetAndRestore ();

+  }

+

+  //

+  // Program processors' registers in sequential mode.

+  //

+  mSetBeforeCpuOnlyReset = FALSE;

+  for (Index = 0; Index < mCpuConfigConextBuffer.NumberOfProcessors; Index++) {

+    

+    ProcessorNumber = mCpuConfigConextBuffer.SettingSequence[Index];

+

+    if (ProcessorNumber == mCpuConfigConextBuffer.BspNumber) {

+      SetProcessorRegister (ProcessorNumber);

+    } else {

+

+      DispatchAPAndWait (

+        FALSE,

+        GET_CPU_MISC_DATA (ProcessorNumber, ApicID),

+        SetProcessorRegister

+        );

+    }

+

+    RegisterTable = &mCpuConfigConextBuffer.RegisterTable[ProcessorNumber];

+    RegisterTable->InitialApicId = GetInitialLocalApicId (ProcessorNumber);

+  }

+  //

+  // Set PcdCpuCallbackSignal to trigger callback function

+  //

+  PcdSet8 (PcdCpuCallbackSignal, CPU_PROCESSOR_SETTING_END_SIGNAL);

+

+  //

+  // From now on, SetProcessorRegister() will be called only by SimpleApProcWrapper()

+  // and ApProcWrapper to restore register settings after INIT signal, so switch

+  // this flag from FALSE to TRUE.

+  //

+  mRestoreSettingAfterInit = TRUE;

+}

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Strings.uni b/IA32FamilyCpuBasePkg/CpuMpDxe/Strings.uni
new file mode 100644
index 0000000..8478d3e
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Strings.uni
Binary files differ
diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Xd.c b/IA32FamilyCpuBasePkg/CpuMpDxe/Xd.c
new file mode 100644
index 0000000..4571684
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Xd.c
@@ -0,0 +1,167 @@
+/** @file

+

+  Code for Execute Disable Bit Feature

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  Xd.c

+

+**/

+

+#include "Xd.h"

+

+BOOLEAN    EnableExecuteDisableBit[FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)];

+

+/**

+  Detect capability of XD feature for specified processor.

+  

+  This function detects capability of XD feature for specified processor.

+

+  @param  ProcessorNumber   The handle number of specified processor.

+

+**/

+VOID

+XdDetect (

+  UINTN   ProcessorNumber

+  )

+{

+  EFI_CPUID_REGISTER  *CpuidRegisters;

+

+  //

+  // Check whether 0x80000001 is supported by CPUID

+  //

+  if (GetNumberOfCpuidLeafs (ProcessorNumber, ExtendedCpuidLeaf) > 2) {

+    //

+    // Check CPUID(0x80000001).EDX[20]

+    //

+    CpuidRegisters = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_EXTENDED_CPU_SIG);

+    ASSERT (CpuidRegisters != NULL);

+

+    if (BitFieldRead32 (CpuidRegisters->RegEdx, N_CPUID_XD_BIT_AVAILABLE, N_CPUID_XD_BIT_AVAILABLE) == 1) {

+      SetProcessorFeatureCapability (ProcessorNumber, ExecuteDisableBit, NULL);

+    }

+  }

+}

+

+/**

+  Configures Processor Feature Lists for XD feature for all processors.

+  

+  This function configures Processor Feature Lists for XD feature for all processors.

+

+**/

+VOID

+XdConfigFeatureList (

+  VOID

+  )

+{

+  UINTN                 ProcessorNumber;

+  BOOLEAN               XdSupported;

+  BOOLEAN               Setting;

+

+  XdSupported = TRUE;

+  Setting = FALSE;

+

+  //

+  // Check whether all logical processors support XD

+  //

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+    if (!GetProcessorFeatureCapability (ProcessorNumber, ExecuteDisableBit, NULL)) {

+      XdSupported = FALSE;

+      break;

+    }

+  }

+  

+  if (XdSupported) {

+    //

+    // Set the bit of XD capability

+    //

+    PcdSet32 (PcdCpuProcessorFeatureCapability, PcdGet32 (PcdCpuProcessorFeatureCapability) | PCD_CPU_EXECUTE_DISABLE_BIT);

+    //

+    // Checks whether user indicates to enable XD

+    //

+    if ((PcdGet32 (PcdCpuProcessorFeatureUserConfiguration) & PCD_CPU_EXECUTE_DISABLE_BIT) != 0) {

+      //

+      // Set the bit of XD setting

+      //

+      PcdSet32 (PcdCpuProcessorFeatureSetting, PcdGet32 (PcdCpuProcessorFeatureSetting) | PCD_CPU_EXECUTE_DISABLE_BIT);

+      Setting = TRUE;

+    }

+  }

+

+  //

+  // If XD is not supported by all logical processors, or user indicates to disable XD, then disable XD on all processors.

+  //

+  for (ProcessorNumber = 0; ProcessorNumber < mCpuConfigConextBuffer.NumberOfProcessors; ProcessorNumber++) {

+    //

+    // The operation can only be performed on the processors supporting XD feature.

+    //

+    if (GetProcessorFeatureCapability (ProcessorNumber, ExecuteDisableBit, NULL)) {

+      EnableExecuteDisableBit[ProcessorNumber] = Setting;

+      AppendProcessorFeatureIntoList (ProcessorNumber, ExecuteDisableBit, &(EnableExecuteDisableBit[ProcessorNumber]));

+    }

+  }

+}

+

+/**

+  Produces entry of XD feature in Register Table for specified processor.

+  

+  This function produces entry of XD feature in Register Table for specified processor.

+

+  @param  ProcessorNumber   The handle number of specified processor.

+  @param  Attribute         Pointer to the attribute

+

+**/

+VOID

+XdReg (

+  UINTN      ProcessorNumber,

+  VOID       *Attribute

+  )

+{

+  BOOLEAN    *Enable;

+  UINT64     Value;

+

+  //

+  // If Attribute is TRUE, then write 0 to MSR_IA32_MISC_ENABLE[34].

+  // Otherwise, write 1 to the bit.

+  //

+  Enable = (BOOLEAN *) Attribute;

+  Value  = 1;

+  if (*Enable) {

+    Value = 0;

+  }

+

+  WriteRegisterTable (

+    ProcessorNumber,

+    Msr,

+    MSR_IA32_MISC_ENABLE,

+    N_MSR_XD_BIT_DISABLE,

+    1,

+    Value

+    );

+}

diff --git a/IA32FamilyCpuBasePkg/CpuMpDxe/Xd.h b/IA32FamilyCpuBasePkg/CpuMpDxe/Xd.h
new file mode 100644
index 0000000..bcaa422
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuMpDxe/Xd.h
@@ -0,0 +1,82 @@
+/** @file

+

+  Include file for Execute Disable Bit Feature

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  Xd.h

+

+**/

+

+#ifndef _CPU_XD_H_

+#define _CPU_XD_H_

+

+#include "MpCommon.h"

+#include "Cpu.h"

+

+/**

+  Detect capability of XD feature for specified processor.

+  

+  This function detects capability of XD feature for specified processor.

+

+  @param  ProcessorNumber   The handle number of specified processor.

+

+**/

+VOID

+XdDetect (

+  UINTN   ProcessorNumber

+  );

+

+/**

+  Configures Processor Feature Lists for XD feature for all processors.

+  

+  This function configures Processor Feature Lists for XD feature for all processors.

+

+**/

+VOID

+XdConfigFeatureList (

+  VOID

+  );

+

+/**

+  Produces entry of XD feature in Register Table for specified processor.

+  

+  This function produces entry of XD feature in Register Table for specified processor.

+

+  @param  ProcessorNumber   The handle number of specified processor.

+  @param  Attribute         Pointer to the attribute

+

+**/

+VOID

+XdReg (

+  UINTN      ProcessorNumber,

+  VOID       *Attribute

+  );

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuPei/Bist.c b/IA32FamilyCpuBasePkg/CpuPei/Bist.c
new file mode 100644
index 0000000..6c0507c
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuPei/Bist.c
@@ -0,0 +1,198 @@
+/** @file

+Implementation of CPU driver for PEI phase.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+Module Name: Bist.c

+

+**/

+

+#include "CpuPei.h"

+#include "Bist.h"

+

+EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPpi = {

+  SecPlatformInformation

+};

+

+EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi = {

+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),

+  &gEfiSecPlatformInformationPpiGuid,

+  &mSecPlatformInformationPpi

+};

+

+/**

+

+  Implementation of the PlatformInformation service

+  

+  Implementation of the PlatformInformation service in EFI_SEC_PLATFORM_INFORMATION_PPI.

+  This function will parse SecPlatform Information from BIST Hob.

+

+  @param  PeiServices                Pointer to the PEI Services Table.

+  @param  StructureSize              Pointer to the variable describing size of the input buffer.

+  @param  PlatformInformationRecord  Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.

+  

+  @retval EFI_SUCCESS                The data was successfully returned.

+  @retval EFI_BUFFER_TOO_SMALL       The buffer was too small.

+  

+**/

+EFI_STATUS

+EFIAPI

+SecPlatformInformation (

+  IN CONST EFI_PEI_SERVICES                  **PeiServices,

+  IN OUT UINT64                              *StructureSize,

+     OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord

+  )

+{

+  EFI_HOB_GUID_TYPE       *GuidHob;

+  VOID                    *DataInHob;

+  UINTN                   DataSize;

+

+  GuidHob = GetFirstGuidHob (&gEfiHtBistHobGuid);

+  if (GuidHob == NULL) {

+    *StructureSize = 0;

+    return EFI_SUCCESS;

+  }

+

+  DataInHob = GET_GUID_HOB_DATA (GuidHob);

+  DataSize  = GET_GUID_HOB_DATA_SIZE (GuidHob);

+

+  //

+  // return the information from BistHob

+  //

+  if ((*StructureSize) < (UINT64) DataSize) {

+    *StructureSize = (UINT64) DataSize;

+    return EFI_BUFFER_TOO_SMALL;

+  }

+

+  *StructureSize = (UINT64) DataSize;

+   

+  CopyMem (PlatformInformationRecord, DataInHob, DataSize);

+

+  return EFI_SUCCESS;

+}

+

+/**

+  A callback function to build CPU(only BSP) BIST. 

+

+  This function is a callback function to build bsp's BIST by calling SecPlatformInformationPpi

+

+  @param  PeiServices      Pointer to PEI Services Table      

+  @param  NotifyDescriptor Address if the notification descriptor data structure 

+  @param  Ppi              Address of the PPI that was installed     

+  @retval EFI_SUCCESS      Retrieve of the BIST data successfully 

+  @retval EFI_SUCCESS      No sec platform information ppi export   

+  @retval EFI_SUCCESS      The boot mode is S3 path   

+**/

+EFI_STATUS

+EFIAPI

+BuildBistHob (

+  IN EFI_PEI_SERVICES           **PeiServices,

+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,

+  IN VOID                       *Ppi

+  )

+{

+  EFI_STATUS                        Status;

+  EFI_BOOT_MODE                     BootMode;

+  EFI_SEC_PLATFORM_INFORMATION_PPI  *SecPlatformInformationPpi;

+  EFI_PEI_PPI_DESCRIPTOR            *SecInformationDescriptor;

+  UINT64                            InformationSize;

+  EFI_SEC_PLATFORM_INFORMATION_RECORD   *SecPlatformInformation;

+

+  Status = (*PeiServices)->GetBootMode (PeiServices, &BootMode);

+  if (!EFI_ERROR (Status) && (BootMode == BOOT_ON_S3_RESUME)) {

+    return EFI_SUCCESS;

+  }

+

+  Status = (*PeiServices)->LocatePpi (

+                             PeiServices,

+                             &gEfiSecPlatformInformationPpiGuid, // GUID

+                             0,                                  // INSTANCE

+                             &SecInformationDescriptor,          // EFI_PEI_PPI_DESCRIPTOR

+                             &SecPlatformInformationPpi          // PPI

+                             );

+

+  if (Status == EFI_NOT_FOUND) {

+    return EFI_SUCCESS;

+  }

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  InformationSize         = 0;

+  SecPlatformInformation  = NULL;

+  Status = SecPlatformInformationPpi->PlatformInformation (

+                                        PeiServices,

+                                        &InformationSize,

+                                        SecPlatformInformation

+                                        );

+  if (Status == EFI_BUFFER_TOO_SMALL) {

+    Status = (*PeiServices)->AllocatePool (

+                               PeiServices,

+                               (UINTN) InformationSize,

+                               &SecPlatformInformation

+                               );

+

+    if (EFI_ERROR (Status)) {

+      return Status;

+    }

+

+    Status = SecPlatformInformationPpi->PlatformInformation (

+                                          PeiServices,

+                                          &InformationSize,

+                                          SecPlatformInformation

+                                          );

+  }

+

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+    BuildGuidDataHob (

+            &gEfiHtBistHobGuid,

+            SecPlatformInformation,

+            (UINTN) InformationSize

+            );

+

+  //

+  // The old SecPlatformInformation Ppi is on CAR.

+  // After memory discovered, we should never get it from CAR, or the data will be crashed.

+  // So, we reinstall SecPlatformInformation PPI here.

+  //

+  Status = (*PeiServices)->ReInstallPpi (

+                             PeiServices,

+                             SecInformationDescriptor,

+                             &mPeiSecPlatformInformationPpi

+                             );

+  if (EFI_ERROR (Status)) {

+    return Status;

+  }

+

+  return Status;

+}

diff --git a/IA32FamilyCpuBasePkg/CpuPei/Bist.h b/IA32FamilyCpuBasePkg/CpuPei/Bist.h
new file mode 100644
index 0000000..01b8b40
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuPei/Bist.h
@@ -0,0 +1,82 @@
+/** @file

+Implementation of CPU driver for PEI phase.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+Module Name: Bist.h

+

+**/

+

+#ifndef _CPU_BIST_H_

+#define _CPU_BIST_H_

+

+/**

+

+  Implementation of the PlatformInformation service

+  

+  Implementation of the PlatformInformation service in EFI_SEC_PLATFORM_INFORMATION_PPI.

+  This function will parse SecPlatform Information from BIST Hob.

+

+  @param  PeiServices                Pointer to the PEI Services Table.

+  @param  StructureSize              Pointer to the variable describing size of the input buffer.

+  @param  PlatformInformationRecord  Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.

+  

+  @retval EFI_SUCCESS                The data was successfully returned.

+  @retval EFI_BUFFER_TOO_SMALL       The buffer was too small.

+  

+**/

+EFI_STATUS

+EFIAPI

+SecPlatformInformation (

+  IN CONST EFI_PEI_SERVICES                   **PeiServices,

+  IN OUT UINT64                               *StructureSize,

+     OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord

+  );

+

+/**

+  A callback function to build CPU(only BSP) BIST. 

+

+  This function is a callback function to build bsp's BIST by calling SecPlatformInformationPpi

+

+  @param  PeiServices      Pointer to PEI Services Table      

+  @param  NotifyDescriptor Address if the notification descriptor data structure 

+  @param  Ppi              Address of the PPI that was installed     

+  @retval EFI_SUCCESS      Retrieve of the BIST data successfully 

+  @retval EFI_SUCCESS      No sec platform information ppi export   

+  @retval EFI_SUCCESS      The boot mode is S3 path   

+**/

+EFI_STATUS

+EFIAPI

+BuildBistHob (

+  IN EFI_PEI_SERVICES           **PeiServices,

+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,

+  IN VOID                       *Ppi

+  );

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuPei/Cache.c b/IA32FamilyCpuBasePkg/CpuPei/Cache.c
new file mode 100644
index 0000000..2ad5223
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuPei/Cache.c
@@ -0,0 +1,156 @@
+/** @file

+Implementation of CPU driver for PEI phase.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+Module Name: Cache.c

+

+**/

+

+#include "CpuPei.h"

+

+/**

+  Reset all the MTRRs to a known state.

+

+  This function provides the PPI for PEI phase to Reset all the MTRRs to a known state(UC)

+  @param  PeiServices     General purpose services available to every PEIM.  

+  @param  This            Current instance of Pei Cache PPI.                 

+

+  @retval EFI_SUCCESS     All MTRRs have been reset successfully.  

+                      

+**/

+EFI_STATUS

+EFIAPI

+PeiResetCacheAttributes (

+  IN  EFI_PEI_SERVICES     **PeiServices,

+  IN  PEI_CACHE_PPI        *This

+  );

+

+/**

+  program the MTRR according to the given range and cache type.

+

+  This function provides the PPI for PEI phase to set the memory attribute by program

+  the MTRR according to the given range and cache type. Actually this function is a 

+  wrapper of the MTRR libaray to suit the PEI_CACHE_PPI interface

+

+  @param  PeiServices     General purpose services available to every PEIM.  

+  @param  This            Current instance of Pei Cache PPI.                 

+  @param  MemoryAddress   Base Address of Memory to program MTRR.            

+  @param  MemoryLength    Length of Memory to program MTRR.                  

+  @param  MemoryCacheType Cache Type.   

+  @retval EFI_SUCCESS             Mtrr are set successfully.        

+  @retval EFI_LOAD_ERROR          No empty MTRRs to use.            

+  @retval EFI_INVALID_PARAMETER   The input parameter is not valid. 

+  @retval others                  An error occurs when setting MTTR.

+                                          

+**/

+EFI_STATUS

+EFIAPI

+PeiSetCacheAttributes (

+  IN  EFI_PEI_SERVICES         **PeiServices,

+  IN  PEI_CACHE_PPI            *This,

+  IN  EFI_PHYSICAL_ADDRESS     MemoryAddress,

+  IN  UINT64                   MemoryLength,

+  IN  EFI_MEMORY_CACHE_TYPE    MemoryCacheType

+  );

+

+PEI_CACHE_PPI   mCachePpi = {

+  PeiSetCacheAttributes,

+  PeiResetCacheAttributes

+};

+

+

+/**

+  program the MTRR according to the given range and cache type.

+

+  This function provides the PPI for PEI phase to set the memory attribute by program

+  the MTRR according to the given range and cache type. Actually this function is a 

+  wrapper of the MTRR libaray to suit the PEI_CACHE_PPI interface

+

+  @param  PeiServices     General purpose services available to every PEIM.  

+  @param  This            Current instance of Pei Cache PPI.                 

+  @param  MemoryAddress   Base Address of Memory to program MTRR.            

+  @param  MemoryLength    Length of Memory to program MTRR.                  

+  @param  MemoryCacheType Cache Type.   

+  @retval EFI_SUCCESS             Mtrr are set successfully.        

+  @retval EFI_LOAD_ERROR          No empty MTRRs to use.            

+  @retval EFI_INVALID_PARAMETER   The input parameter is not valid. 

+  @retval others                  An error occurs when setting MTTR.

+                                          

+**/

+EFI_STATUS

+EFIAPI

+PeiSetCacheAttributes (

+  IN EFI_PEI_SERVICES          **PeiServices,

+  IN PEI_CACHE_PPI             *This,

+  IN EFI_PHYSICAL_ADDRESS      MemoryAddress,

+  IN UINT64                    MemoryLength,

+  IN EFI_MEMORY_CACHE_TYPE     MemoryCacheType

+  )

+{

+

+   RETURN_STATUS            Status;

+   //

+   // call MTRR libary function

+   //

+   Status = MtrrSetMemoryAttribute(

+              MemoryAddress,

+              MemoryLength,

+              (MTRR_MEMORY_CACHE_TYPE) MemoryCacheType

+            );

+   return (EFI_STATUS)Status;

+}

+/**

+  Reset all the MTRRs to a known state.

+

+  This function provides the PPI for PEI phase to Reset all the MTRRs to a known state(UC)

+  @param  PeiServices     General purpose services available to every PEIM.  

+  @param  This            Current instance of Pei Cache PPI.                 

+

+  @retval EFI_SUCCESS     All MTRRs have been reset successfully.  

+                      

+**/

+EFI_STATUS

+EFIAPI

+PeiResetCacheAttributes (

+  IN EFI_PEI_SERVICES          **PeiServices,

+  IN PEI_CACHE_PPI             *This

+  )

+{

+

+   MTRR_SETTINGS  ZeroMtrr;

+   

+   //

+   // reset all Mtrrs to 0 include fixed MTRR and variable MTRR

+   //

+   ZeroMem(&ZeroMtrr, sizeof(MTRR_SETTINGS));

+   MtrrSetAllMtrrs(&ZeroMtrr);

+   

+   return EFI_SUCCESS;

+}

diff --git a/IA32FamilyCpuBasePkg/CpuPei/CpuPei.h b/IA32FamilyCpuBasePkg/CpuPei/CpuPei.h
new file mode 100644
index 0000000..53da573
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuPei/CpuPei.h
@@ -0,0 +1,58 @@
+/** @file

+Implementation of CPU driver for PEI phase.

+

+This PEIM is to expose the CPUIO ppi, Cache Ppi and BIST hob build notification

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+**/

+

+#ifndef _PEI_CPUPEIM_H_

+#define _PEI_CPUPEIM_H_

+

+

+#include <PiPei.h>

+

+#include <Ppi/Cache.h>

+#include <Ppi/MasterBootMode.h>

+#include <Ppi/SecPlatformInformation.h>

+#include <Guid/HtBistHob.h>

+

+#include <Library/DebugLib.h>

+#include <Library/PeimEntryPoint.h>

+#include <Library/BaseLib.h>

+#include <Library/PeiServicesLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/HobLib.h>

+#include <Library/MtrrLib.h>

+#include <Library/PcdLib.h>

+#include <Library/SocketLga775Lib.h>

+#include <Library/ReportStatusCodeLib.h>

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf b/IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf
new file mode 100644
index 0000000..50f06ca
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf
@@ -0,0 +1,85 @@
+## @file

+# Implementation of CPU driver for PEI phase.

+#

+# This PEIM is to expose the CPUIO ppi, Cache Ppi and BIST hob build notification

+# Copyright (c) 2013 Intel Corporation.

+#

+# Redistribution and use in source and binary forms, with or without

+# modification, are permitted provided that the following conditions

+# are met:

+#

+# * Redistributions of source code must retain the above copyright

+# notice, this list of conditions and the following disclaimer.

+# * Redistributions in binary form must reproduce the above copyright

+# notice, this list of conditions and the following disclaimer in

+# the documentation and/or other materials provided with the

+# distribution.

+# * Neither the name of Intel Corporation nor the names of its

+# contributors may be used to endorse or promote products derived

+# from this software without specific prior written permission.

+#

+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+#

+#

+##

+

+[Defines]

+  INF_VERSION                    = 0x00010005

+  BASE_NAME                      = CpuPei

+  FILE_GUID                      = 01359D99-9446-456d-ADA4-50A711C03ADA

+  MODULE_TYPE                    = PEIM

+  VERSION_STRING                 = 1.0

+  ENTRY_POINT                    = CpuPeimInit

+

+#

+# The following information is for reference only and not required by the build tools.

+#

+#  VALID_ARCHITECTURES           = IA32 X64

+#

+#  HOB Guid C Name: gEfiHtBistHobGuid Hob Type: GUID_EXTENSION

+#

+

+[Sources]

+  Bist.h

+  Bist.c

+  Cache.c

+  CpuPei.h

+  CpuPeim.c

+

+[Packages]

+  MdePkg/MdePkg.dec

+  UefiCpuPkg/UefiCpuPkg.dec

+  IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec

+

+[LibraryClasses]

+  PcdLib

+  MtrrLib

+  HobLib

+  BaseMemoryLib

+  PeiServicesLib

+  BaseLib

+  PeimEntryPoint

+  DebugLib

+  ReportStatusCodeLib

+

+[Guids]

+  gEfiHtBistHobGuid                             # ALWAYS_CONSUMED

+

+[Ppis]

+  gEfiPeiMasterBootModePpiGuid                  # PPI_NOTIFY SOMETIMES_CONSUMED

+  gEfiSecPlatformInformationPpiGuid             # PPI SOMETIMES_CONSUMED

+  gPeiCachePpiGuid                              # PPI ALWAYS_PRODUCED

+

+[Depex]

+  TRUE

+  
\ No newline at end of file
diff --git a/IA32FamilyCpuBasePkg/CpuPei/CpuPeim.c b/IA32FamilyCpuBasePkg/CpuPei/CpuPeim.c
new file mode 100644
index 0000000..e2b6ceb
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/CpuPei/CpuPeim.c
@@ -0,0 +1,141 @@
+/** @file

+Implementation of CPU driver for PEI phase.

+

+This PEIM is to expose the Cache Ppi and BIST hob build notification

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+  

+Module Name: CpuPeim.c

+

+**/

+

+#include "CpuPei.h"

+#include "Bist.h"

+

+extern PEI_CACHE_PPI                mCachePpi;

+//

+// Ppis to be installed

+//

+EFI_PEI_PPI_DESCRIPTOR           mPpiList[] = { 

+  {

+    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),

+    &gPeiCachePpiGuid,

+    &mCachePpi

+  }

+};

+

+//

+// Notification to build BIST information

+//

+STATIC EFI_PEI_NOTIFY_DESCRIPTOR        mNotifyList[] = {

+  {

+    (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),

+    &gEfiPeiMasterBootModePpiGuid,

+    BuildBistHob

+  }

+};

+

+/**

+  Initialize SSE support.

+**/

+VOID

+InitXMM (

+  VOID

+  )

+{

+

+  UINT32  RegEdx;

+

+  AsmCpuid (EFI_CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);

+

+  //

+  //Check whether SSE2 is supported

+  //

+  if ((RegEdx & BIT26) == 0) {

+    AsmWriteCr0 (AsmReadCr0 () | BIT1);

+    AsmWriteCr4 (AsmReadCr4 () | BIT9 | BIT10);

+  }

+}

+

+

+/**

+  The Entry point of the CPU PEIM

+

+  This function is the Entry point of the CPU PEIM which will install the CachePpi and 

+  BuildBISTHob notifier. And also the function will deal with the relocation to memory when 

+  permanent memory is ready

+ 

+  @param  FileHandle  Handle of the file being invoked.

+  @param  PeiServices Describes the list of possible PEI Services. 

+                          

+  @retval EFI_SUCCESS   CachePpi and BIST hob build notification is installed

+                        successfully.

+

+**/

+EFI_STATUS

+EFIAPI

+CpuPeimInit (

+  IN       EFI_PEI_FILE_HANDLE  FileHandle,

+  IN CONST EFI_PEI_SERVICES     **PeiServices

+  )

+{

+	EFI_STATUS  Status;

+

+  //

+  // Report Status Code to indicate the start of CPU PEIM

+  //

+  REPORT_STATUS_CODE (

+    EFI_PROGRESS_CODE,

+    EFI_COMPUTING_UNIT_HOST_PROCESSOR + EFI_CU_HP_PC_POWER_ON_INIT

+    );

+

+  //

+  // Install PPIs

+  //

+  Status = PeiServicesInstallPpi(&mPpiList[0]);

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Register for PPI Notifications

+  //

+  Status = PeiServicesNotifyPpi (&mNotifyList[0]);

+  ASSERT_EFI_ERROR (Status);

+

+  //

+  // Report Status Code to indicate the start of CPU PEI initialization

+  //

+  REPORT_STATUS_CODE (

+    EFI_PROGRESS_CODE,

+    EFI_COMPUTING_UNIT_HOST_PROCESSOR + EFI_CU_PC_INIT_BEGIN

+    );

+   

+  InitXMM ();

+  

+  return Status;

+}

diff --git a/IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec b/IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
new file mode 100644
index 0000000..629185b
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dec
@@ -0,0 +1,144 @@
+## @file

+# Package for support of IA32 family processors

+#

+# This package supports IA32 family processors, with CPU DXE module, CPU PEIM, CPU S3 module,

+# SMM modules, related libraries, and corresponding definitions.

+#

+# Copyright (c) 2013 Intel Corporation.

+#

+# Redistribution and use in source and binary forms, with or without

+# modification, are permitted provided that the following conditions

+# are met:

+#

+# * Redistributions of source code must retain the above copyright

+# notice, this list of conditions and the following disclaimer.

+# * Redistributions in binary form must reproduce the above copyright

+# notice, this list of conditions and the following disclaimer in

+# the documentation and/or other materials provided with the

+# distribution.

+# * Neither the name of Intel Corporation nor the names of its

+# contributors may be used to endorse or promote products derived

+# from this software without specific prior written permission.

+#

+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+#

+##

+

+[Defines]

+  DEC_SPECIFICATION              = 0x00010005

+  PACKAGE_NAME                   = IA32FamilyCpuBasePkg

+  PACKAGE_GUID                   = 6E0E3B55-5650-4265-A4D9-849D19D6D609

+  PACKAGE_VERSION                = 0.4

+

+[Includes]

+  Include

+

+[LibraryClasses]

+  CpuConfigLib|Include/Library/CpuConfigLib.h

+  CpuOnlyResetLib|Include/Library/CpuOnlyResetLib.h

+  PlatformSecLib|Include/Library/PlatformSecLib.h

+  Socket775LgaLib|Include/Library/SocketLga775Lib.h

+  SmmCpuPlatformHookLib|Include/Library/SmmCpuPlatformHookLib.h

+

+[Guids]

+  gEfiHtBistHobGuid              = { 0xBE644001, 0xE7D4, 0x48B1, { 0xB0, 0x96, 0x8B, 0xA0, 0x47, 0xBC, 0x7A, 0xE7 }}

+  gEfiCpuTokenSpaceGuid          = { 0x2ADA836D, 0x0A3D, 0x43D6, { 0xA2, 0x5A, 0x38, 0x45, 0xCA, 0xD2, 0xD4, 0x00 }}

+

+[Ppis]

+  gPeiCachePpiGuid               = { 0xC153205A, 0xE898, 0x4C24, { 0x86, 0x89, 0xA4, 0xB4, 0xBC, 0xC5, 0xC8, 0xA2 }}

+

+[Protocols]

+  gSmmCpuSyncProtocolGuid        = { 0xd5950985, 0x8be3, 0x4b1c, { 0xb6, 0x3f, 0x95, 0xd1, 0x5a, 0xb3, 0xb6, 0x5f }}

+  gSmmCpuSync2ProtocolGuid       = { 0x9db72e22, 0x9262, 0x4a18, { 0x8f, 0xe0, 0x85, 0xe0, 0x3d, 0xfa, 0x96, 0x73 }}

+  gEfiSmmCpuServiceProtocolGuid  = { 0x1d202cab, 0xc8ab, 0x4d5c, { 0x94, 0xf7, 0x3c, 0xfc, 0xc0, 0xd3, 0xd3, 0x35 }}

+

+[PcdsFeatureFlag]

+  gEfiCpuTokenSpaceGuid.PcdCpuMaxCpuIDValueLimitFlag|TRUE|BOOLEAN|0x10000008

+  gEfiCpuTokenSpaceGuid.PcdCpuSelectLfpAsBspFlag|FALSE|BOOLEAN|0x1000000F

+  gEfiCpuTokenSpaceGuid.PcdCpuSmmEnableBspElection|TRUE|BOOLEAN|0x32132106

+  gEfiCpuTokenSpaceGuid.PcdCpuExecuteDisableBitFlag|TRUE|BOOLEAN|0x10000009

+  gEfiCpuTokenSpaceGuid.PcdCpuSmmDebug|FALSE|BOOLEAN|0x1000001B

+  gEfiCpuTokenSpaceGuid.PcdCpuSmmStackGuard|FALSE|BOOLEAN|0x1000001C

+  gEfiCpuTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp|FALSE|BOOLEAN|0x32132108

+  gEfiCpuTokenSpaceGuid.PcdCpuSmmProfileEnable|FALSE|BOOLEAN|0x32132109

+  gEfiCpuTokenSpaceGuid.PcdCpuSmmProfileRingBuffer|FALSE|BOOLEAN|0x3213210a

+

+  gEfiCpuTokenSpaceGuid.PcdCpuSmmUncacheCpuSyncData|FALSE|BOOLEAN|0x3213210D

+  gEfiCpuTokenSpaceGuid.PcdCpuHotPlugSupport|FALSE|BOOLEAN|0x3213210C

+  gEfiCpuTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock|TRUE|BOOLEAN|0x3213210B

+

+[PcdsFixedAtBuild]

+  gEfiCpuTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber|64|UINT32|0x30000002

+  gEfiCpuTokenSpaceGuid.PcdCpuSmmApSyncTimeout|1000000|UINT64|0x32132104

+  gEfiCpuTokenSpaceGuid.PcdCpuSmmStackSize|0x2000|UINT32|0x32132105

+  ##

+  #  The PCD is used to specify memory size with bytes to save SMM profile data.

+  #  The value should be a multiple of 4KB.

+  ##

+  gEfiCpuTokenSpaceGuid.PcdCpuSmmProfileSize|0x200000|UINT32|0x32132107

+

+  ##

+  #  Maximum number of Ppi is provided by SecCore.

+  ##

+  gEfiCpuTokenSpaceGuid.PcdSecCoreMaxPpiSupported|0x6|UINT32|0x10001010

+  gEfiCpuTokenSpaceGuid.PcdTemporaryRamBase|0xfef00000|UINT32|0x10001001

+  gEfiCpuTokenSpaceGuid.PcdTemporaryRamSize|0x2000|UINT32|0x10001002

+  gEfiCpuTokenSpaceGuid.PcdSecMaximumNumberOfProcessors|1|UINT32|0x10001000

+

+[PcdsFixedAtBuild, PcdsPatchableInModule]

+  ## Stack size in the temporary RAM.

+  #   0 means half of TemporaryRamSize.

+  gEfiCpuTokenSpaceGuid.PcdPeiTemporaryRamStackSize|0|UINT32|0x10001003

+

+[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]

+  gEfiCpuTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds|50000|UINT32|0x30000001

+  gEfiCpuTokenSpaceGuid.PcdCpuApStackSize|0x8000|UINT32|0x30000003

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureUserConfiguration|0|UINT32|0x40000001

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureUserConfigurationEx1|0|UINT32|0x40000006

+  gEfiCpuTokenSpaceGuid.PcdPlatformHighPowerLoadLineSupport|TRUE|BOOLEAN|0x60000001

+  gEfiCpuTokenSpaceGuid.PcdPlatformDynamicVidSupport|TRUE|BOOLEAN|0x60000002

+  gEfiCpuTokenSpaceGuid.PcdPlatformType|0|UINT8|0x60000003

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxCoreFrequency|0x0|UINT32|0x60000004

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxFsbFrequency|0x0|UINT32|0x60000005

+  ## Base address of the LVL_2 register visible to software.

+  # 16-bit IO port address.

+  gEfiCpuTokenSpaceGuid.PcdCpuAcpiLvl2Addr|0x0|UINT16|0x60008001

+  ## This PCD specifies the AP wait loop mode during POST.

+  #  The value is defined as below.

+  #  1: ApInHltLoop,   AP is in the Hlt-Loop state.

+  #  2: ApInMwaitLoop, AP is in the Mwait-Loop state.

+  #  3: ApInRunLoop,   AP is in the Run-Loop state.

+  gEfiCpuTokenSpaceGuid.PcdCpuApLoopMode|1|UINT8|0x60008006

+

+  gEfiCpuTokenSpaceGuid.PcdCpuSmmCodeAccessCheckEnable|TRUE|BOOLEAN|0x60000013

+  ## This PCD specifies the TCC Activation Offset value

+  gEfiCpuTokenSpaceGuid.PcdCpuTccActivationOffset|0|UINT8|0x6000001B

+

+[PcdsDynamic, PcdsDynamicEx]

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureCapability|0|UINT32|0x40000002

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureSetting|0|UINT32|0x40000003

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureCapabilityEx1|0|UINT32|0x40000004

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureSettingEx1|0|UINT32|0x40000005

+  gEfiCpuTokenSpaceGuid.PcdCpuConfigContextBuffer|0x0|UINT64|0x50000001

+  gEfiCpuTokenSpaceGuid.PcdCpuCallbackSignal|0x0|UINT8|0x50000002

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuFrequencyLists|0x0|UINT64|0x60000006

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketCount|0x0|UINT32|0x60000012

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketNames|0x0|UINT64|0x60000007

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuAssetTags|0x0|UINT64|0x60000008

+  gEfiCpuTokenSpaceGuid.PcdIsPowerOnReset|FALSE|BOOLEAN|0x6000000F

+  gEfiCpuTokenSpaceGuid.PcdCpuPageTableAddress|0x0|UINT64|0x6000000E

+  gEfiCpuTokenSpaceGuid.PcdCpuMtrrTableAddress|0x0|UINT64|0x6000000D

+  gEfiCpuTokenSpaceGuid.PcdCpuS3DataAddress|0x0|UINT64|0x60000010

+  gEfiCpuTokenSpaceGuid.PcdCpuSocketId|{0}|VOID*|0x60008007

+  gEfiCpuTokenSpaceGuid.PcdCpuHotPlugDataAddress|0x0|UINT64|0x60000011

+

diff --git a/IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dsc b/IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dsc
new file mode 100644
index 0000000..e60defa
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/IA32FamilyCpuBasePkg.dsc
@@ -0,0 +1,207 @@
+## @file

+# Package description file for IA32FamilyCpuBasePkg.

+#

+# This DSC file is used for Package Level build.

+#

+# Copyright (c) 2013 Intel Corporation.

+#

+# Redistribution and use in source and binary forms, with or without

+# modification, are permitted provided that the following conditions

+# are met:

+#

+# * Redistributions of source code must retain the above copyright

+# notice, this list of conditions and the following disclaimer.

+# * Redistributions in binary form must reproduce the above copyright

+# notice, this list of conditions and the following disclaimer in

+# the documentation and/or other materials provided with the

+# distribution.

+# * Neither the name of Intel Corporation nor the names of its

+# contributors may be used to endorse or promote products derived

+# from this software without specific prior written permission.

+#

+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+#

+##

+

+################################################################################

+#

+# Defines Section - statements that will be processed to create a Makefile.

+#

+################################################################################

+[Defines]

+  PLATFORM_NAME                  = IA32FamilyCpuBasePkg

+  PLATFORM_GUID                  = 54BABF97-1B9B-4fe0-847E-AFA0DF0F26F9

+  PLATFORM_VERSION               = 0.4

+  DSC_SPECIFICATION              = 0x00010005

+  OUTPUT_DIRECTORY               = Build/IA32FamilyCpuBasePkg

+  SUPPORTED_ARCHITECTURES        = IA32|X64

+  BUILD_TARGETS                  = DEBUG|RELEASE

+  SKUID_IDENTIFIER               = DEFAULT

+

+################################################################################

+#

+# SKU Identification section - list of all SKU IDs supported by this

+#                              Platform.

+#

+################################################################################

+[SkuIds]

+  0|DEFAULT              # The entry: 0|DEFAULT is reserved and always required.

+

+

+################################################################################

+#

+# Library Class section - list of all Library Classes needed by this Platform.

+#

+################################################################################

+[LibraryClasses]

+  CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf

+  DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf

+  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf

+  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf

+  SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf

+  CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf

+  BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf

+  PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf

+  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf

+  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf

+  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf

+  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf

+  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf

+  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf

+  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf

+  CpuOnlyResetLib|IA32FamilyCpuBasePkg/Library/CpuOnlyResetLibNull/CpuOnlyResetLibNull.inf

+  PlatformSecLib|IA32FamilyCpuBasePkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf

+  DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf

+  UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf

+  SmbusLib|MdePkg/Library/DxeSmbusLib/DxeSmbusLib.inf

+  MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf

+  CpuConfigLib|IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfigLib.inf

+  DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf

+  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf

+

+  PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf

+  PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf

+  PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf

+  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf

+  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf

+  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf

+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf

+  DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf

+  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf

+  S3IoLib|MdePkg/Library/BaseS3IoLib/BaseS3IoLib.inf

+  S3PciLib|MdePkg/Library/BaseS3PciLib/BaseS3PciLib.inf

+  S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf

+  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf

+  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf

+  SmmLib|MdePkg/Library/SmmLibNull/SmmLibNull.inf

+  LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf

+  OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf  

+  ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf

+

+[LibraryClasses.common.PEIM]

+  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf

+  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf

+  PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf

+  SmbusLib|MdePkg/Library/PeiSmbusLibSmbus2Ppi/PeiSmbusLibSmbus2Ppi.inf

+  ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf

+  LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf

+

+[LibraryClasses.common.DXE_DRIVER]

+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf

+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf

+  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf

+  DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf

+  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf

+  LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf

+

+[LibraryClasses.common.DXE_RUNTIME_DRIVER]

+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf

+  LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf

+

+[LibraryClasses.common.DXE_SMM_DRIVER]

+  SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf

+  MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf

+  ReportStatusCodeLib|MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf

+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf

+  LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf

+  SmmCpuPlatformHookLib|IA32FamilyCpuBasePkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLibNull.inf

+

+################################################################################

+#

+# Pcd Section - list of all EDK II PCD Entries defined by this Platform

+#

+################################################################################

+[PcdsFeatureFlag]

+  gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable|TRUE

+  gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable|TRUE

+  gEfiCpuTokenSpaceGuid.PcdCpuSmmEnableBspElection|FALSE

+  gEfiCpuTokenSpaceGuid.PcdCpuSelectLfpAsBspFlag|TRUE

+

+[PcdsFixedAtBuild]

+  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f

+  gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxFsbFrequency|1066

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuMaxCoreFrequency|3800

+

+################################################################################

+#

+# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform

+#

+################################################################################

+

+[PcdsDynamicDefault.common.DEFAULT]

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureUserConfiguration|0xffffffff

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureCapability|0

+  gEfiCpuTokenSpaceGuid.PcdCpuProcessorFeatureSetting|0

+  gEfiCpuTokenSpaceGuid.PcdCpuConfigContextBuffer|0

+  gEfiCpuTokenSpaceGuid.PcdCpuCallbackSignal|0

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuFrequencyLists|0

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuSocketNames|0

+  gEfiCpuTokenSpaceGuid.PcdPlatformCpuAssetTags|0

+  gEfiCpuTokenSpaceGuid.PcdCpuPageTableAddress|0

+  gEfiCpuTokenSpaceGuid.PcdCpuMtrrTableAddress|0

+  gEfiCpuTokenSpaceGuid.PcdIsPowerOnReset|FALSE

+

+###################################################################################################

+#

+# Components Section - list of the modules and components that will be processed by compilation

+#                      tools and the EDK II tools to generate PE32/PE32+/Coff image files.

+#

+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed

+#       into firmware volume images. This section is just a list of modules to compile from

+#       source into UEFI-compliant binaries.

+#       It is the FDF file that contains information on combining binary files into firmware

+#       volume images, whose concept is beyond UEFI and is described in PI specification.

+#       Binary modules do not need to be listed in this section, as they should be

+#       specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),

+#       Logo (Logo.bmp), and etc.

+#       There may also be modules listed in this section that are not required in the FDF file,

+#       When a module listed here is excluded from FDF file, then UEFI-compliant binary will be

+#       generated for it, but the binary will not be put into any firmware volume.

+#

+###################################################################################################

+

+[Components]

+  IA32FamilyCpuBasePkg/Library/CpuConfigLib/CpuConfigLib.inf

+  IA32FamilyCpuBasePkg/Library/CpuLocalApicTimerLib/CpuLocalApicTimerLib.inf

+  IA32FamilyCpuBasePkg/Library/CpuOnlyResetLibNull/CpuOnlyResetLibNull.inf

+  IA32FamilyCpuBasePkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf

+  IA32FamilyCpuBasePkg/SecCore/SecCore.inf

+  IA32FamilyCpuBasePkg/SecCore/Vtf0SecCore.inf

+  IA32FamilyCpuBasePkg/CpuArchDxe/CpuArchDxe.inf

+  IA32FamilyCpuBasePkg/CpuMpDxe/CpuMpDxe.inf

+  IA32FamilyCpuBasePkg/CpuPei/CpuPei.inf

+  IA32FamilyCpuBasePkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf

+  IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationPei.inf

+  IA32FamilyCpuBasePkg/PiSmmCommunication/PiSmmCommunicationSmm.inf

+

diff --git a/IA32FamilyCpuBasePkg/Include/AcpiCpuData.h b/IA32FamilyCpuBasePkg/Include/AcpiCpuData.h
new file mode 100644
index 0000000..371996a
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/AcpiCpuData.h
@@ -0,0 +1,53 @@
+/** @file

+  Definitions for CPU S3 data.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+**/

+

+#ifndef _ACPI_CPU_DATA_H_

+#define _ACPI_CPU_DATA_H_

+

+typedef struct {

+  BOOLEAN               APState;

+  EFI_PHYSICAL_ADDRESS  StartupVector;

+  EFI_PHYSICAL_ADDRESS  GdtrProfile;

+  EFI_PHYSICAL_ADDRESS  IdtrProfile;

+  EFI_PHYSICAL_ADDRESS  StackAddress;

+  UINT32                StackSize;

+  UINT32                NumberOfCpus;

+  EFI_PHYSICAL_ADDRESS  MtrrTable;

+  EFI_PHYSICAL_ADDRESS  PreSmmInitRegisterTable;

+  EFI_PHYSICAL_ADDRESS  RegisterTable;

+  EFI_PHYSICAL_ADDRESS  ApMachineCheckHandlerBase;

+  UINT32                ApMachineCheckHandlerSize;

+} ACPI_CPU_DATA;

+

+#endif

+

diff --git a/IA32FamilyCpuBasePkg/Include/CpuHotPlugData.h b/IA32FamilyCpuBasePkg/Include/CpuHotPlugData.h
new file mode 100644
index 0000000..aa4e638
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/CpuHotPlugData.h
@@ -0,0 +1,52 @@
+/** @file

+  Definition for a struture sharing information for CPU hot plug.

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+**/

+#ifndef _CPU_HOT_PLUG_DATA_H_

+#define _CPU_HOT_PLUG_DATA_H_

+

+typedef struct {

+  //

+  // Placeholder for MP intialization data

+  //

+

+  //

+  // Data required for SMBASE relocation

+  //

+  UINT64    ApicId[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];

+  UINTN     SmBase[FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber)];

+  UINT32    SmrrBase;

+  UINT32    SmrrSize;

+

+} CPU_HOT_PLUG_DATA;

+

+#endif

+

diff --git a/IA32FamilyCpuBasePkg/Include/Guid/HtBistHob.h b/IA32FamilyCpuBasePkg/Include/Guid/HtBistHob.h
new file mode 100644
index 0000000..08aa3fa
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Guid/HtBistHob.h
@@ -0,0 +1,52 @@
+/** @file

+

+Copyright (c) 2013 Intel Corporation.

+

+Redistribution and use in source and binary forms, with or without

+modification, are permitted provided that the following conditions

+are met:

+

+* Redistributions of source code must retain the above copyright

+notice, this list of conditions and the following disclaimer.

+* Redistributions in binary form must reproduce the above copyright

+notice, this list of conditions and the following disclaimer in

+the documentation and/or other materials provided with the

+distribution.

+* Neither the name of Intel Corporation nor the names of its

+contributors may be used to endorse or promote products derived

+from this software without specific prior written permission.

+

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+

+Module Name:

+

+  HtBistHob.h

+    

+Abstract:

+

+  GUID used for HT BIST Status HOB entries in the HOB list.

+

+**/

+

+#ifndef _HT_BIST_HOB_GUID_H_

+#define _HT_BIST_HOB_GUID_H_

+

+#define EFI_HT_BIST_HOB_GUID \

+  { \

+    0xbe644001, 0xe7d4, 0x48b1, {0xb0, 0x96, 0x8b, 0xa0, 0x47, 0xbc, 0x7a, 0xe7 } \

+  }

+

+extern EFI_GUID gEfiHtBistHobGuid;

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/Include/Guid/IA32FamilyCpuPkgTokenSpace.h b/IA32FamilyCpuBasePkg/Include/Guid/IA32FamilyCpuPkgTokenSpace.h
new file mode 100644
index 0000000..ca24575
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Guid/IA32FamilyCpuPkgTokenSpace.h
@@ -0,0 +1,44 @@
+/** @file

+  GUID for IA32FamilyCpuBasePkg PCD Token Space 

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+**/

+

+#ifndef _IA32FAMILYCPUPKG_TOKEN_SPACE_GUID_H_

+#define _IA32FAMILYCPUPKG_TOKEN_SPACE_GUID_H_

+

+#define CPU_TOKEN_SPACE_GUID \

+  { \

+    0x2ADA836D, 0x0A3D, 0x43D6, { 0xA2, 0x5A, 0x38, 0x45, 0xCA, 0xD2, 0xD4, 0x00 } \

+  }

+

+extern EFI_GUID gEfiCpuTokenSpaceGuid;

+

+#endif

diff --git a/IA32FamilyCpuBasePkg/Include/Library/CpuConfigLib.h b/IA32FamilyCpuBasePkg/Include/Library/CpuConfigLib.h
new file mode 100644
index 0000000..39c7ce9
--- /dev/null
+++ b/IA32FamilyCpuBasePkg/Include/Library/CpuConfigLib.h
@@ -0,0 +1,702 @@
+/** @file

+  Public include file for the CPU Configuration Library

+

+  Copyright (c) 2013 Intel Corporation.

+

+  Redistribution and use in source and binary forms, with or without

+  modification, are permitted provided that the following conditions

+  are met:

+

+  * Redistributions of source code must retain the above copyright

+  notice, this list of conditions and the following disclaimer.

+  * Redistributions in binary form must reproduce the above copyright

+  notice, this list of conditions and the following disclaimer in

+  the documentation and/or other materials provided with the

+  distribution.

+  * Neither the name of Intel Corporation nor the names of its

+  contributors may be used to endorse or promote products derived

+  from this software without specific prior written permission.

+

+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+

+  Module Name:  CpuConfigLib.h

+

+**/

+

+#ifndef _CPU_CONFIG_LIB_H_

+#define _CPU_CONFIG_LIB_H_

+

+//

+// Bits definition of PcdProcessorFeatureUserConfiguration,

+// PcdProcessorFeatureCapability, and PcdProcessorFeatureSetting

+//

+#define PCD_CPU_HT_BIT                           0x00000001

+#define PCD_CPU_CMP_BIT                          0x00000002

+#define PCD_CPU_L2_CACHE_BIT                     0x00000004

+#define PCD_CPU_L2_ECC_BIT                       0x00000008

+#define PCD_CPU_VT_BIT                           0x00000010

+#define PCD_CPU_LT_BIT                           0x00000020

+#define PCD_CPU_EXECUTE_DISABLE_BIT              0x00000040

+#define PCD_CPU_L3_CACHE_BIT                     0x00000080

+#define PCD_CPU_MAX_CPUID_VALUE_LIMIT_BIT        0x00000100

+#define PCD_CPU_FAST_STRING_BIT                  0x00000200

+#define PCD_CPU_FERR_SIGNAL_BREAK_BIT            0x00000400

+#define PCD_CPU_PECI_BIT                         0x00000800

+#define PCD_CPU_HARDWARE_PREFETCHER_BIT          0x00001000

+#define PCD_CPU_ADJACENT_CACHE_LINE_PREFETCH_BIT 0x00002000

+#define PCD_CPU_DCU_PREFETCHER_BIT               0x00004000

+#define PCD_CPU_IP_PREFETCHER_BIT                0x00008000

+#define PCD_CPU_MACHINE_CHECK_BIT                0x00010000

+#define PCD_CPU_THERMAL_MANAGEMENT_BIT           0x00040000

+#define PCD_CPU_EIST_BIT                         0x00080000

+#define PCD_CPU_C1E_BIT                          0x00200000

+#define PCD_CPU_C2E_BIT                          0x00400000

+#define PCD_CPU_C3E_BIT                          0x00800000

+#define PCD_CPU_C4E_BIT                          0x01000000

+#define PCD_CPU_HARD_C4E_BIT                     0x02000000

+#define PCD_CPU_DEEP_C4_BIT                      0x04000000

+#define PCD_CPU_A20M_DISABLE_BIT                 0x08000000

+#define PCD_CPU_MONITOR_MWAIT_BIT                0x10000000

+#define PCD_CPU_TSTATE_BIT                       0x20000000

+#define PCD_CPU_TURBO_MODE_BIT                   0x80000000

+

+//

+// Bits definition of PcdProcessorFeatureUserConfigurationEx1,

+// PcdProcessorFeatureCapabilityEx1, and PcdProcessorFeatureSettingEx1

+//

+#define PCD_CPU_C_STATE_BIT                      0x00000001

+#define PCD_CPU_C1_AUTO_DEMOTION_BIT             0x00000002

+#define PCD_CPU_C3_AUTO_DEMOTION_BIT             0x00000004

+#define PCD_CPU_MLC_STREAMER_PREFETCHER_BIT      0x00000008

+#define PCD_CPU_MLC_SPATIAL_PREFETCHER_BIT       0x00000010

+#define PCD_CPU_THREE_STRIKE_COUNTER_BIT         0x00000020

+#define PCD_CPU_ENERGY_PERFORMANCE_BIAS_BIT      0x00000040

+#define PCD_CPU_DCA_BIT                          0x00000080

+#define PCD_CPU_X2APIC_BIT                       0x00000100

+#define PCD_CPU_AES_BIT                          0x00000200

+#define PCD_CPU_APIC_TPR_UPDATE_MESSAGE_BIT      0x00000400

+#define PCD_CPU_SOCKET_ID_REASSIGNMENT_BIT       0x00000800

+

+//

+// Value definition for PcdCpuCallbackSignal

+//

+#define CPU_BYPASS_SIGNAL                        0x00000000

+#define CPU_DATA_COLLECTION_SIGNAL               0x00000001

+#define CPU_PROCESSOR_FEATURE_LIST_CONFIG_SIGNAL 0x00000002

+#define CPU_REGISTER_TABLE_TRANSLATION_SIGNAL    0x00000003

+#define CPU_PROCESSOR_SETTING_SIGNAL             0x00000004

+#define CPU_PROCESSOR_SETTING_END_SIGNAL         0x00000005

+

+typedef struct {

+  UINT32  RegEax;

+  UINT32  RegEbx;

+  UINT32  RegEcx;

+  UINT32  RegEdx;

+} EFI_CPUID_REGISTER;

+

+//

+// Enumeration of processor features

+//

+typedef enum {

+  Ht,

+  Cmp,

+  Vt,

+  ExecuteDisableBit,

+  L3Cache,

+  MaxCpuidValueLimit,

+  FastString,

+  FerrSignalBreak,

+  Peci,

+  HardwarePrefetcher,

+  AdjacentCacheLinePrefetch,

+  DcuPrefetcher,

+  IpPrefetcher,

+  ThermalManagement,

+  Eist,

+  BiDirectionalProchot,

+  Forcepr,

+  C1e,

+  C2e,

+  C3e,

+  C4e,

+  HardC4e,

+  DeepC4,

+  Microcode,

+  Microcode2,

+  MachineCheck,

+  GateA20MDisable,

+  MonitorMwait,

+  TState,

+  TurboMode,

+  CState,

+  C1AutoDemotion,

+  C3AutoDemotion,

+  MlcStreamerPrefetcher,

+  MlcSpatialPrefetcher,

+  ThreeStrikeCounter,

+  EnergyPerformanceBias,

+  Dca,

+  X2Apic,

+  Aes,

+  ApicTprUpdateMessage,

+  TccActivation,

+  CpuFeatureMaximum

+} CPU_FEATURE_ID;

+

+//

+// Structure for collected processor feature capability,

+// and feature-specific attribute.

+//

+typedef struct {

+  BOOLEAN                 Capability;

+  VOID                    *Attribute;

+} CPU_FEATURE_DATA;

+

+//

+// Structure for collected CPUID data.

+//

+typedef struct {

+  EFI_CPUID_REGISTER         *CpuIdLeaf;

+  UINTN                      NumberOfBasicCpuidLeafs;

+  UINTN                      NumberOfExtendedCpuidLeafs;

+  UINTN                      NumberOfCacheAndTlbCpuidLeafs;

+  UINTN                      NumberOfDeterministicCacheParametersCpuidLeafs;

+  UINTN                      NumberOfExtendedTopologyEnumerationLeafs;

+} CPU_CPUID_DATA;

+

+typedef struct {

+  UINTN    Ratio;

+  UINTN    Vid;

+  UINTN    Power;

+  UINTN    TransitionLatency;

+  UINTN    BusMasterLatency;

+} FVID_ENTRY;

+

+//

+// Miscellaneous processor data

+//

+typedef struct {

+  //

+  // Local Apic Data

+  //

+  UINT32                     InitialApicID;  ///< Initial APIC ID

+  UINT32                     ApicID;         ///< Current APIC ID

+  EFI_PHYSICAL_ADDRESS       ApicBase;

+  UINT32                     ApicVersion;

+  //

+  // Frequency data

+  //

+  UINTN                      IntendedFsbFrequency;

+  UINTN                      ActualFsbFrequency;

+  BOOLEAN                    FrequencyLocked;

+  UINTN                      MaxCoreToBusRatio;

+  UINT