]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
UefiCpuPkg/PiSmmCpuDxeSmm: Enable MM MP Protocol
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / PiSmmCpuDxeSmm.h
index 71af2f17759560c3a4a24bcfb628bf669864e8d2..186809f43119e5d6af88e5732fbcc3a7ada8299d 100644 (file)
@@ -1,16 +1,10 @@
 /** @file\r
 Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.\r
 \r
-Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>\r
 Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
 \r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -25,8 +19,11 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/SmmAccess2.h>\r
 #include <Protocol/SmmReadyToLock.h>\r
 #include <Protocol/SmmCpuService.h>\r
+#include <Protocol/SmmMemoryAttribute.h>\r
+#include <Protocol/MmMp.h>\r
 \r
 #include <Guid/AcpiS3Context.h>\r
+#include <Guid/MemoryAttributesTable.h>\r
 #include <Guid/PiSmmMemoryAttributesTable.h>\r
 \r
 #include <Library/BaseLib.h>\r
@@ -36,7 +33,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/DebugLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/PcdLib.h>\r
-#include <Library/CacheMaintenanceLib.h>\r
 #include <Library/MtrrLib.h>\r
 #include <Library/SmmCpuPlatformHookLib.h>\r
 #include <Library/SmmServicesTableLib.h>\r
@@ -44,6 +40,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/UefiRuntimeServicesTableLib.h>\r
 #include <Library/DebugAgentLib.h>\r
+#include <Library/UefiLib.h>\r
 #include <Library/HobLib.h>\r
 #include <Library/LocalApicLib.h>\r
 #include <Library/UefiCpuLib.h>\r
@@ -51,6 +48,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/ReportStatusCodeLib.h>\r
 #include <Library/SmmCpuFeaturesLib.h>\r
 #include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/RegisterCpuFeaturesLib.h>\r
 \r
 #include <AcpiCpuData.h>\r
 #include <CpuHotPlugData.h>\r
@@ -61,6 +59,51 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "CpuService.h"\r
 #include "SmmProfile.h"\r
 \r
+//\r
+// CET definition\r
+//\r
+#define CPUID_CET_SS   BIT7\r
+#define CPUID_CET_IBT  BIT20\r
+\r
+#define CR4_CET_ENABLE  BIT23\r
+\r
+#define MSR_IA32_S_CET                     0x6A2\r
+#define MSR_IA32_PL0_SSP                   0x6A4\r
+#define MSR_IA32_INTERRUPT_SSP_TABLE_ADDR  0x6A8\r
+\r
+typedef union {\r
+  struct {\r
+    // enable shadow stacks\r
+    UINT32  SH_STK_ENP:1;\r
+    // enable the WRSS{D,Q}W instructions.\r
+    UINT32  WR_SHSTK_EN:1;\r
+    // enable tracking of indirect call/jmp targets to be ENDBRANCH instruction.\r
+    UINT32  ENDBR_EN:1;\r
+    // enable legacy compatibility treatment for indirect call/jmp tracking.\r
+    UINT32  LEG_IW_EN:1;\r
+    // enable use of no-track prefix on indirect call/jmp.\r
+    UINT32  NO_TRACK_EN:1;\r
+    // disable suppression of CET indirect branch tracking on legacy compatibility.\r
+    UINT32  SUPPRESS_DIS:1;\r
+    UINT32  RSVD:4;\r
+    // indirect branch tracking is suppressed.\r
+    // This bit can be written to 1 only if TRACKER is written as IDLE.\r
+    UINT32  SUPPRESS:1;\r
+    // Value of the endbranch state machine\r
+    // Values: IDLE (0), WAIT_FOR_ENDBRANCH(1).\r
+    UINT32  TRACKER:1;\r
+    // linear address of a bitmap in memory indicating valid\r
+    // pages as target of CALL/JMP_indirect that do not land on ENDBRANCH when CET is enabled\r
+    // and not suppressed. Valid when ENDBR_EN is 1. Must be machine canonical when written on\r
+    // parts that support 64 bit mode. On parts that do not support 64 bit mode, the bits 63:32 are\r
+    // reserved and must be 0. This value is extended by 12 bits at the low end to form the base address\r
+    // (this automatically aligns the address on a 4-Kbyte boundary).\r
+    UINT32  EB_LEG_BITMAP_BASE_low:12;\r
+    UINT32  EB_LEG_BITMAP_BASE_high:32;\r
+  } Bits;\r
+  UINT64   Uint64;\r
+} MSR_IA32_CET;\r
+\r
 //\r
 // MSRs required for configuration of SMM Code Access Check\r
 //\r
@@ -105,6 +148,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull\r
 #define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull\r
 \r
+#define SMRR_MAX_ADDRESS       BASE_4GB\r
+\r
 typedef enum {\r
   PageNone,\r
   Page4K,\r
@@ -122,9 +167,11 @@ typedef struct {
 // Size of Task-State Segment defined in IA32 Manual\r
 //\r
 #define TSS_SIZE              104\r
+#define EXCEPTION_TSS_SIZE    (TSS_SIZE + 4) // Add 4 bytes SSP\r
 #define TSS_X64_IST1_OFFSET   36\r
 #define TSS_IA32_CR3_OFFSET   28\r
 #define TSS_IA32_ESP_OFFSET   56\r
+#define TSS_IA32_SSP_OFFSET   104\r
 \r
 #define CR0_WP                BIT16\r
 \r
@@ -151,6 +198,25 @@ typedef UINT32                              SMM_CPU_ARRIVAL_EXCEPTIONS;
 #define ARRIVAL_EXCEPTION_DELAYED           0x2\r
 #define ARRIVAL_EXCEPTION_SMI_DISABLED      0x4\r
 \r
+//\r
+// Wrapper used to convert EFI_AP_PROCEDURE2 and EFI_AP_PROCEDURE.\r
+//\r
+typedef struct {\r
+  EFI_AP_PROCEDURE  Procedure;\r
+  VOID              *ProcedureArgument;\r
+} PROCEDURE_WRAPPER;\r
+\r
+#define PROCEDURE_TOKEN_SIGNATURE  SIGNATURE_32 ('P', 'R', 'T', 'S')\r
+\r
+typedef struct {\r
+  UINTN                   Signature;\r
+  LIST_ENTRY              Link;\r
+\r
+  SPIN_LOCK               *ProcedureToken;\r
+} PROCEDURE_TOKEN;\r
+\r
+#define PROCEDURE_TOKEN_FROM_LINK(a)  CR (a, PROCEDURE_TOKEN, Link, PROCEDURE_TOKEN_SIGNATURE)\r
+\r
 //\r
 // Private structure for the SMM CPU module that is stored in DXE Runtime memory\r
 // Contains the SMM Configuration Protocols that is produced.\r
@@ -173,6 +239,10 @@ typedef struct {
   EFI_SMM_ENTRY_POINT             SmmCoreEntry;\r
 \r
   EFI_SMM_CONFIGURATION_PROTOCOL  SmmConfiguration;\r
+\r
+  PROCEDURE_WRAPPER               *ApWrapperFunc;\r
+  LIST_ENTRY                      TokenList;\r
+\r
 } SMM_CPU_PRIVATE_DATA;\r
 \r
 extern SMM_CPU_PRIVATE_DATA  *gSmmCpuPrivate;\r
@@ -180,6 +250,7 @@ extern CPU_HOT_PLUG_DATA      mCpuHotPlugData;
 extern UINTN                  mMaxNumberOfCpus;\r
 extern UINTN                  mNumberOfCpus;\r
 extern EFI_SMM_CPU_PROTOCOL   mSmmCpu;\r
+extern EFI_MM_MP_PROTOCOL     mSmmMp;\r
 \r
 ///\r
 /// The mode of the CPU at the time an SMI occurs\r
@@ -292,23 +363,16 @@ WriteSaveStateRegister (
   IN CONST VOID                   *Buffer\r
   );\r
 \r
-//\r
-//\r
-//\r
-typedef struct {\r
-  UINT32                            Offset;\r
-  UINT16                            Segment;\r
-  UINT16                            Reserved;\r
-} IA32_FAR_ADDRESS;\r
-\r
-extern IA32_FAR_ADDRESS             gSmmJmpAddr;\r
-\r
 extern CONST UINT8                  gcSmmInitTemplate[];\r
 extern CONST UINT16                 gcSmmInitSize;\r
-extern UINT32                       gSmmCr0;\r
-extern UINT32                       gSmmCr3;\r
-extern UINT32                       gSmmCr4;\r
-extern UINTN                        gSmmInitStack;\r
+X86_ASSEMBLY_PATCH_LABEL            gPatchSmmCr0;\r
+extern UINT32                       mSmmCr0;\r
+X86_ASSEMBLY_PATCH_LABEL            gPatchSmmCr3;\r
+extern UINT32                       mSmmCr4;\r
+X86_ASSEMBLY_PATCH_LABEL            gPatchSmmCr4;\r
+X86_ASSEMBLY_PATCH_LABEL            gPatchSmmInitStack;\r
+X86_ASSEMBLY_PATCH_LABEL            mPatchCetSupported;\r
+extern BOOLEAN                      mCetSupported;\r
 \r
 /**\r
   Semaphore operation for all processor relocate SMMBase.\r
@@ -324,10 +388,12 @@ SmmRelocationSemaphoreComplete (
 ///\r
 typedef struct {\r
   SPIN_LOCK                         *Busy;\r
-  volatile EFI_AP_PROCEDURE         Procedure;\r
+  volatile EFI_AP_PROCEDURE2        Procedure;\r
   volatile VOID                     *Parameter;\r
   volatile UINT32                   *Run;\r
   volatile BOOLEAN                  *Present;\r
+  SPIN_LOCK                         *Token;\r
+  EFI_STATUS                        *Status;\r
 } SMM_CPU_DATA_BLOCK;\r
 \r
 typedef enum {\r
@@ -349,15 +415,10 @@ typedef struct {
   volatile SMM_CPU_SYNC_MODE    EffectiveSyncMode;\r
   volatile BOOLEAN              SwitchBsp;\r
   volatile BOOLEAN              *CandidateBsp;\r
+  EFI_AP_PROCEDURE              StartupProcedure;\r
+  VOID                          *StartupProcArgs;\r
 } SMM_DISPATCHER_MP_SYNC_DATA;\r
 \r
-#define MSR_SPIN_LOCK_INIT_NUM 15\r
-\r
-typedef struct {\r
-  SPIN_LOCK    *SpinLock;\r
-  UINT32       MsrIndex;\r
-} MP_MSR_LOCK;\r
-\r
 #define SMM_PSD_OFFSET              0xfb00\r
 \r
 ///\r
@@ -369,7 +430,6 @@ typedef struct {
   volatile BOOLEAN     *AllCpusInSync;\r
   SPIN_LOCK            *PFLock;\r
   SPIN_LOCK            *CodeAccessCheckLock;\r
-  SPIN_LOCK            *MemoryMappedLock;\r
 } SMM_CPU_SEMAPHORE_GLOBAL;\r
 \r
 ///\r
@@ -379,23 +439,15 @@ typedef struct {
   SPIN_LOCK                         *Busy;\r
   volatile UINT32                   *Run;\r
   volatile BOOLEAN                  *Present;\r
+  SPIN_LOCK                         *Token;\r
 } SMM_CPU_SEMAPHORE_CPU;\r
 \r
-///\r
-/// All MSRs semaphores' pointer and counter\r
-///\r
-typedef struct {\r
-  SPIN_LOCK            *Msr;\r
-  UINTN                AvailableCounter;\r
-} SMM_CPU_SEMAPHORE_MSR;\r
-\r
 ///\r
 /// All semaphores' information\r
 ///\r
 typedef struct {\r
   SMM_CPU_SEMAPHORE_GLOBAL          SemaphoreGlobal;\r
   SMM_CPU_SEMAPHORE_CPU             SemaphoreCpu;\r
-  SMM_CPU_SEMAPHORE_MSR             SemaphoreMsr;\r
 } SMM_CPU_SEMAPHORES;\r
 \r
 extern IA32_DESCRIPTOR                     gcSmiGdtr;\r
@@ -414,7 +466,9 @@ extern SMM_CPU_SEMAPHORES                  mSmmCpuSemaphores;
 extern UINTN                               mSemaphoreSize;\r
 extern SPIN_LOCK                           *mPFLock;\r
 extern SPIN_LOCK                           *mConfigSmmCodeAccessCheckLock;\r
-extern SPIN_LOCK                           *mMemoryMappedLock;\r
+extern EFI_SMRAM_DESCRIPTOR                *mSmmCpuSmramRanges;\r
+extern UINTN                               mSmmCpuSmramRangeCount;\r
+extern UINT8                               mPhysicalAddressBits;\r
 \r
 //\r
 // Copy of the PcdPteMemoryEncryptionAddressOrMask\r
@@ -437,14 +491,16 @@ Gen4GPageTable (
 /**\r
   Initialize global data for MP synchronization.\r
 \r
-  @param Stacks       Base address of SMI stack buffer for all processors.\r
-  @param StackSize    Stack size for each processor in SMM.\r
+  @param Stacks             Base address of SMI stack buffer for all processors.\r
+  @param StackSize          Stack size for each processor in SMM.\r
+  @param ShadowStackSize    Shadow Stack size for each processor in SMM.\r
 \r
 **/\r
 UINT32\r
 InitializeMpServiceData (\r
   IN VOID        *Stacks,\r
-  IN UINTN       StackSize\r
+  IN UINTN       StackSize,\r
+  IN UINTN       ShadowStackSize\r
   );\r
 \r
 /**\r
@@ -503,14 +559,6 @@ InitGdt (
   OUT UINTN  *GdtStepSize\r
   );\r
 \r
-/**\r
-  This function sets GDT/IDT buffer to be RO and XP.\r
-**/\r
-VOID\r
-PatchGdtIdtMap (\r
-  VOID\r
-  );\r
-\r
 /**\r
 \r
   Register the SMM Foundation entry point.\r
@@ -690,8 +738,8 @@ SmmRelocateBases (
 VOID\r
 EFIAPI\r
 SmiPFHandler (\r
-    IN EFI_EXCEPTION_TYPE   InterruptType,\r
-    IN EFI_SYSTEM_CONTEXT   SystemContext\r
+  IN EFI_EXCEPTION_TYPE   InterruptType,\r
+  IN EFI_SYSTEM_CONTEXT   SystemContext\r
   );\r
 \r
 /**\r
@@ -1063,4 +1111,343 @@ TransferApToSafeState (
   IN UINTN  NumberToFinishAddress\r
   );\r
 \r
+/**\r
+  Set ShadowStack memory.\r
+\r
+  @param[in]  Cr3              The page table base address.\r
+  @param[in]  BaseAddress      The physical address that is the start address of a memory region.\r
+  @param[in]  Length           The size in bytes of the memory region.\r
+\r
+  @retval EFI_SUCCESS           The shadow stack memory is set.\r
+**/\r
+EFI_STATUS\r
+SetShadowStack (\r
+  IN  UINTN                                      Cr3,\r
+  IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,\r
+  IN  UINT64                                     Length\r
+  );\r
+\r
+/**\r
+  Set not present memory.\r
+\r
+  @param[in]  Cr3              The page table base address.\r
+  @param[in]  BaseAddress      The physical address that is the start address of a memory region.\r
+  @param[in]  Length           The size in bytes of the memory region.\r
+\r
+  @retval EFI_SUCCESS           The not present memory is set.\r
+**/\r
+EFI_STATUS\r
+SetNotPresentPage (\r
+  IN  UINTN                                      Cr3,\r
+  IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,\r
+  IN  UINT64                                     Length\r
+  );\r
+\r
+/**\r
+  Initialize the shadow stack related data structure.\r
+\r
+  @param CpuIndex     The index of CPU.\r
+  @param ShadowStack  The bottom of the shadow stack for this CPU.\r
+**/\r
+VOID\r
+InitShadowStack (\r
+  IN UINTN  CpuIndex,\r
+  IN VOID   *ShadowStack\r
+  );\r
+\r
+/**\r
+  This function set given attributes of the memory region specified by\r
+  BaseAddress and Length.\r
+\r
+  @param  This              The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.\r
+  @param  BaseAddress       The physical address that is the start address of\r
+                            a memory region.\r
+  @param  Length            The size in bytes of the memory region.\r
+  @param  Attributes        The bit mask of attributes to set for the memory\r
+                            region.\r
+\r
+  @retval EFI_SUCCESS           The attributes were set for the memory region.\r
+  @retval EFI_INVALID_PARAMETER Length is zero.\r
+                                Attributes specified an illegal combination of\r
+                                attributes that cannot be set together.\r
+  @retval EFI_UNSUPPORTED       The processor does not support one or more\r
+                                bytes of the memory resource range specified\r
+                                by BaseAddress and Length.\r
+                                The bit mask of attributes is not supported for\r
+                                the memory resource range specified by\r
+                                BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EdkiiSmmSetMemoryAttributes (\r
+  IN  EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL   *This,\r
+  IN  EFI_PHYSICAL_ADDRESS                  BaseAddress,\r
+  IN  UINT64                                Length,\r
+  IN  UINT64                                Attributes\r
+  );\r
+\r
+/**\r
+  This function clears given attributes of the memory region specified by\r
+  BaseAddress and Length.\r
+\r
+  @param  This              The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.\r
+  @param  BaseAddress       The physical address that is the start address of\r
+                            a memory region.\r
+  @param  Length            The size in bytes of the memory region.\r
+  @param  Attributes        The bit mask of attributes to clear for the memory\r
+                            region.\r
+\r
+  @retval EFI_SUCCESS           The attributes were cleared for the memory region.\r
+  @retval EFI_INVALID_PARAMETER Length is zero.\r
+                                Attributes specified an illegal combination of\r
+                                attributes that cannot be cleared together.\r
+  @retval EFI_UNSUPPORTED       The processor does not support one or more\r
+                                bytes of the memory resource range specified\r
+                                by BaseAddress and Length.\r
+                                The bit mask of attributes is not supported for\r
+                                the memory resource range specified by\r
+                                BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EdkiiSmmClearMemoryAttributes (\r
+  IN  EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL   *This,\r
+  IN  EFI_PHYSICAL_ADDRESS                  BaseAddress,\r
+  IN  UINT64                                Length,\r
+  IN  UINT64                                Attributes\r
+  );\r
+\r
+/**\r
+  This function retrieves the attributes of the memory region specified by\r
+  BaseAddress and Length. If different attributes are got from different part\r
+  of the memory region, EFI_NO_MAPPING will be returned.\r
+\r
+  @param  This              The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.\r
+  @param  BaseAddress       The physical address that is the start address of\r
+                            a memory region.\r
+  @param  Length            The size in bytes of the memory region.\r
+  @param  Attributes        Pointer to attributes returned.\r
+\r
+  @retval EFI_SUCCESS           The attributes got for the memory region.\r
+  @retval EFI_INVALID_PARAMETER Length is zero.\r
+                                Attributes is NULL.\r
+  @retval EFI_NO_MAPPING        Attributes are not consistent cross the memory\r
+                                region.\r
+  @retval EFI_UNSUPPORTED       The processor does not support one or more\r
+                                bytes of the memory resource range specified\r
+                                by BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EdkiiSmmGetMemoryAttributes (\r
+  IN  EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL   *This,\r
+  IN  EFI_PHYSICAL_ADDRESS                  BaseAddress,\r
+  IN  UINT64                                Length,\r
+  IN  UINT64                                *Attributes\r
+  );\r
+\r
+/**\r
+  This function fixes up the address of the global variable or function\r
+  referred in SmmInit assembly files to be the absoute address.\r
+**/\r
+VOID\r
+EFIAPI\r
+PiSmmCpuSmmInitFixupAddress (\r
+ );\r
+\r
+/**\r
+  This function fixes up the address of the global variable or function\r
+  referred in SmiEntry assembly files to be the absoute address.\r
+**/\r
+VOID\r
+EFIAPI\r
+PiSmmCpuSmiEntryFixupAddress (\r
+ );\r
+\r
+/**\r
+  This function reads CR2 register when on-demand paging is enabled\r
+  for 64 bit and no action for 32 bit.\r
+\r
+  @param[out]  *Cr2  Pointer to variable to hold CR2 register value.\r
+**/\r
+VOID\r
+SaveCr2 (\r
+  OUT UINTN  *Cr2\r
+  );\r
+\r
+/**\r
+  This function writes into CR2 register when on-demand paging is enabled\r
+  for 64 bit and no action for 32 bit.\r
+\r
+  @param[in]  Cr2  Value to write into CR2 register.\r
+**/\r
+VOID\r
+RestoreCr2 (\r
+  IN UINTN  Cr2\r
+  );\r
+\r
+/**\r
+  Schedule a procedure to run on the specified CPU.\r
+\r
+  @param[in]       Procedure                The address of the procedure to run\r
+  @param[in]       CpuIndex                 Target CPU Index\r
+  @param[in,out]   ProcArguments            The parameter to pass to the procedure\r
+  @param[in,out]   Token                    This is an optional parameter that allows the caller to execute the\r
+                                            procedure in a blocking or non-blocking fashion. If it is NULL the\r
+                                            call is blocking, and the call will not return until the AP has\r
+                                            completed the procedure. If the token is not NULL, the call will\r
+                                            return immediately. The caller can check whether the procedure has\r
+                                            completed with CheckOnProcedure or WaitForProcedure.\r
+  @param[in]       TimeoutInMicroseconds    Indicates the time limit in microseconds for the APs to finish\r
+                                            execution of Procedure, either for blocking or non-blocking mode.\r
+                                            Zero means infinity. If the timeout expires before all APs return\r
+                                            from Procedure, then Procedure on the failed APs is terminated. If\r
+                                            the timeout expires in blocking mode, the call returns EFI_TIMEOUT.\r
+                                            If the timeout expires in non-blocking mode, the timeout determined\r
+                                            can be through CheckOnProcedure or WaitForProcedure.\r
+                                            Note that timeout support is optional. Whether an implementation\r
+                                            supports this feature can be determined via the Attributes data\r
+                                            member.\r
+  @param[in,out]   CPUStatus                This optional pointer may be used to get the status code returned\r
+                                            by Procedure when it completes execution on the target AP, or with\r
+                                            EFI_TIMEOUT if the Procedure fails to complete within the optional\r
+                                            timeout. The implementation will update this variable with\r
+                                            EFI_NOT_READY prior to starting Procedure on the target AP.\r
+\r
+  @retval EFI_INVALID_PARAMETER    CpuNumber not valid\r
+  @retval EFI_INVALID_PARAMETER    CpuNumber specifying BSP\r
+  @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber did not enter SMM\r
+  @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber is busy\r
+  @retval EFI_SUCCESS              The procedure has been successfully scheduled\r
+\r
+**/\r
+EFI_STATUS\r
+InternalSmmStartupThisAp (\r
+  IN      EFI_AP_PROCEDURE2              Procedure,\r
+  IN      UINTN                          CpuIndex,\r
+  IN OUT  VOID                           *ProcArguments OPTIONAL,\r
+  IN      MM_COMPLETION                  *Token,\r
+  IN      UINTN                          TimeoutInMicroseconds,\r
+  IN OUT  EFI_STATUS                     *CpuStatus\r
+  );\r
+\r
+/**\r
+  Checks whether the input token is the current used token.\r
+\r
+  @param[in]  Token      This parameter describes the token that was passed into DispatchProcedure or\r
+                         BroadcastProcedure.\r
+\r
+  @retval TRUE           The input token is the current used token.\r
+  @retval FALSE          The input token is not the current used token.\r
+**/\r
+BOOLEAN\r
+IsTokenInUse (\r
+  IN SPIN_LOCK           *Token\r
+  );\r
+\r
+/**\r
+  Checks status of specified AP.\r
+\r
+  This function checks whether the specified AP has finished the task assigned\r
+  by StartupThisAP(), and whether timeout expires.\r
+\r
+  @param[in]  Token             This parameter describes the token that was passed into DispatchProcedure or\r
+                                BroadcastProcedure.\r
+\r
+  @retval EFI_SUCCESS           Specified AP has finished task assigned by StartupThisAPs().\r
+  @retval EFI_NOT_READY         Specified AP has not finished task and timeout has not expired.\r
+**/\r
+EFI_STATUS\r
+IsApReady (\r
+  IN SPIN_LOCK  *Token\r
+  );\r
+\r
+/**\r
+  Check whether it is an present AP.\r
+\r
+  @param   CpuIndex      The AP index which calls this function.\r
+\r
+  @retval  TRUE           It's a present AP.\r
+  @retval  TRUE           This is not an AP or it is not present.\r
+\r
+**/\r
+BOOLEAN\r
+IsPresentAp (\r
+  IN UINTN        CpuIndex\r
+  );\r
+\r
+/**\r
+  Worker function to execute a caller provided function on all enabled APs.\r
+\r
+  @param[in]     Procedure               A pointer to the function to be run on\r
+                                         enabled APs of the system.\r
+  @param[in]     TimeoutInMicroseconds   Indicates the time limit in microseconds for\r
+                                         APs to return from Procedure, either for\r
+                                         blocking or non-blocking mode.\r
+  @param[in,out] ProcedureArgument       The parameter passed into Procedure for\r
+                                         all APs.\r
+  @param[in,out] Token                   This is an optional parameter that allows the caller to execute the\r
+                                         procedure in a blocking or non-blocking fashion. If it is NULL the\r
+                                         call is blocking, and the call will not return until the AP has\r
+                                         completed the procedure. If the token is not NULL, the call will\r
+                                         return immediately. The caller can check whether the procedure has\r
+                                         completed with CheckOnProcedure or WaitForProcedure.\r
+  @param[in,out] CPUStatus               This optional pointer may be used to get the status code returned\r
+                                         by Procedure when it completes execution on the target AP, or with\r
+                                         EFI_TIMEOUT if the Procedure fails to complete within the optional\r
+                                         timeout. The implementation will update this variable with\r
+                                         EFI_NOT_READY prior to starting Procedure on the target AP.\r
+\r
+  @retval EFI_SUCCESS             In blocking mode, all APs have finished before\r
+                                  the timeout expired.\r
+  @retval EFI_SUCCESS             In non-blocking mode, function has been dispatched\r
+                                  to all enabled APs.\r
+  @retval others                  Failed to Startup all APs.\r
+\r
+**/\r
+EFI_STATUS\r
+InternalSmmStartupAllAPs (\r
+  IN       EFI_AP_PROCEDURE2             Procedure,\r
+  IN       UINTN                         TimeoutInMicroseconds,\r
+  IN OUT   VOID                          *ProcedureArguments OPTIONAL,\r
+  IN OUT   MM_COMPLETION                 *Token,\r
+  IN OUT   EFI_STATUS                    *CPUStatus\r
+  );\r
+\r
+/**\r
+\r
+  Register the SMM Foundation entry point.\r
+\r
+  @param[in]      Procedure            A pointer to the code stream to be run on the designated target AP\r
+                                       of the system. Type EFI_AP_PROCEDURE is defined below in Volume 2\r
+                                       with the related definitions of\r
+                                       EFI_MP_SERVICES_PROTOCOL.StartupAllAPs.\r
+                                       If caller may pass a value of NULL to deregister any existing\r
+                                       startup procedure.\r
+  @param[in,out]  ProcedureArguments   Allows the caller to pass a list of parameters to the code that is\r
+                                       run by the AP. It is an optional common mailbox between APs and\r
+                                       the caller to share information\r
+\r
+  @retval EFI_SUCCESS                  The Procedure has been set successfully.\r
+  @retval EFI_INVALID_PARAMETER        The Procedure is NULL but ProcedureArguments not NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+RegisterStartupProcedure (\r
+  IN EFI_AP_PROCEDURE    Procedure,\r
+  IN VOID                *ProcedureArguments OPTIONAL\r
+  );\r
+\r
+/**\r
+  Allocate buffer for SpinLock and Wrapper function buffer.\r
+\r
+**/\r
+VOID\r
+InitializeDataForMmMp (\r
+  VOID\r
+  );\r
+\r
 #endif\r