REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3283 Current SMM Save State routine does not check the number of bytes to be read, when it comse to read IO_INFO, before casting the incoming buffer to EFI_SMM_SAVE_STATE_IO_INFO. This could potentially cause memory corruption due to extra bytes are written out of buffer boundary. This change adds a width check before copying IoInfo into output buffer. Cc: Eric Dong <eric.dong@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Laszlo Ersek <lersek@redhat.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Signed-off-by: Kun Qin <kuqin12@gmail.com> Reviewed-by: Ray Ni <ray.ni@intel.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Message-Id: <20210406195254.1018-2-kuqin12@gmail.com>
		
			
				
	
	
		
			1480 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1480 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
 | |
| 
 | |
| Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
 | |
| Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
 | |
| 
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #ifndef _CPU_PISMMCPUDXESMM_H_
 | |
| #define _CPU_PISMMCPUDXESMM_H_
 | |
| 
 | |
| #include <PiSmm.h>
 | |
| 
 | |
| #include <Protocol/MpService.h>
 | |
| #include <Protocol/SmmConfiguration.h>
 | |
| #include <Protocol/SmmCpu.h>
 | |
| #include <Protocol/SmmAccess2.h>
 | |
| #include <Protocol/SmmReadyToLock.h>
 | |
| #include <Protocol/SmmCpuService.h>
 | |
| #include <Protocol/SmmMemoryAttribute.h>
 | |
| #include <Protocol/MmMp.h>
 | |
| 
 | |
| #include <Guid/AcpiS3Context.h>
 | |
| #include <Guid/MemoryAttributesTable.h>
 | |
| #include <Guid/PiSmmMemoryAttributesTable.h>
 | |
| 
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/IoLib.h>
 | |
| #include <Library/TimerLib.h>
 | |
| #include <Library/SynchronizationLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/PcdLib.h>
 | |
| #include <Library/MtrrLib.h>
 | |
| #include <Library/SmmCpuPlatformHookLib.h>
 | |
| #include <Library/SmmServicesTableLib.h>
 | |
| #include <Library/MemoryAllocationLib.h>
 | |
| #include <Library/UefiBootServicesTableLib.h>
 | |
| #include <Library/UefiRuntimeServicesTableLib.h>
 | |
| #include <Library/DebugAgentLib.h>
 | |
| #include <Library/UefiLib.h>
 | |
| #include <Library/HobLib.h>
 | |
| #include <Library/LocalApicLib.h>
 | |
| #include <Library/UefiCpuLib.h>
 | |
| #include <Library/CpuExceptionHandlerLib.h>
 | |
| #include <Library/ReportStatusCodeLib.h>
 | |
| #include <Library/SmmCpuFeaturesLib.h>
 | |
| #include <Library/PeCoffGetEntryPointLib.h>
 | |
| #include <Library/RegisterCpuFeaturesLib.h>
 | |
| 
 | |
| #include <AcpiCpuData.h>
 | |
| #include <CpuHotPlugData.h>
 | |
| 
 | |
| #include <Register/Intel/Cpuid.h>
 | |
| #include <Register/Intel/Msr.h>
 | |
| 
 | |
| #include "CpuService.h"
 | |
| #include "SmmProfile.h"
 | |
| 
 | |
| //
 | |
| // CET definition
 | |
| //
 | |
| #define CPUID_CET_SS   BIT7
 | |
| #define CPUID_CET_IBT  BIT20
 | |
| 
 | |
| #define CR4_CET_ENABLE  BIT23
 | |
| 
 | |
| #define MSR_IA32_S_CET                     0x6A2
 | |
| #define MSR_IA32_PL0_SSP                   0x6A4
 | |
| #define MSR_IA32_INTERRUPT_SSP_TABLE_ADDR  0x6A8
 | |
| 
 | |
| typedef union {
 | |
|   struct {
 | |
|     // enable shadow stacks
 | |
|     UINT32  SH_STK_ENP:1;
 | |
|     // enable the WRSS{D,Q}W instructions.
 | |
|     UINT32  WR_SHSTK_EN:1;
 | |
|     // enable tracking of indirect call/jmp targets to be ENDBRANCH instruction.
 | |
|     UINT32  ENDBR_EN:1;
 | |
|     // enable legacy compatibility treatment for indirect call/jmp tracking.
 | |
|     UINT32  LEG_IW_EN:1;
 | |
|     // enable use of no-track prefix on indirect call/jmp.
 | |
|     UINT32  NO_TRACK_EN:1;
 | |
|     // disable suppression of CET indirect branch tracking on legacy compatibility.
 | |
|     UINT32  SUPPRESS_DIS:1;
 | |
|     UINT32  RSVD:4;
 | |
|     // indirect branch tracking is suppressed.
 | |
|     // This bit can be written to 1 only if TRACKER is written as IDLE.
 | |
|     UINT32  SUPPRESS:1;
 | |
|     // Value of the endbranch state machine
 | |
|     // Values: IDLE (0), WAIT_FOR_ENDBRANCH(1).
 | |
|     UINT32  TRACKER:1;
 | |
|     // linear address of a bitmap in memory indicating valid
 | |
|     // pages as target of CALL/JMP_indirect that do not land on ENDBRANCH when CET is enabled
 | |
|     // and not suppressed. Valid when ENDBR_EN is 1. Must be machine canonical when written on
 | |
|     // parts that support 64 bit mode. On parts that do not support 64 bit mode, the bits 63:32 are
 | |
|     // reserved and must be 0. This value is extended by 12 bits at the low end to form the base address
 | |
|     // (this automatically aligns the address on a 4-Kbyte boundary).
 | |
|     UINT32  EB_LEG_BITMAP_BASE_low:12;
 | |
|     UINT32  EB_LEG_BITMAP_BASE_high:32;
 | |
|   } Bits;
 | |
|   UINT64   Uint64;
 | |
| } MSR_IA32_CET;
 | |
| 
 | |
| //
 | |
| // MSRs required for configuration of SMM Code Access Check
 | |
| //
 | |
| #define EFI_MSR_SMM_MCA_CAP                    0x17D
 | |
| #define  SMM_CODE_ACCESS_CHK_BIT               BIT58
 | |
| 
 | |
| #define  SMM_FEATURE_CONTROL_LOCK_BIT          BIT0
 | |
| #define  SMM_CODE_CHK_EN_BIT                   BIT2
 | |
| 
 | |
| ///
 | |
| /// Page Table Entry
 | |
| ///
 | |
| #define IA32_PG_P                   BIT0
 | |
| #define IA32_PG_RW                  BIT1
 | |
| #define IA32_PG_U                   BIT2
 | |
| #define IA32_PG_WT                  BIT3
 | |
| #define IA32_PG_CD                  BIT4
 | |
| #define IA32_PG_A                   BIT5
 | |
| #define IA32_PG_D                   BIT6
 | |
| #define IA32_PG_PS                  BIT7
 | |
| #define IA32_PG_PAT_2M              BIT12
 | |
| #define IA32_PG_PAT_4K              IA32_PG_PS
 | |
| #define IA32_PG_PMNT                BIT62
 | |
| #define IA32_PG_NX                  BIT63
 | |
| 
 | |
| #define PAGE_ATTRIBUTE_BITS         (IA32_PG_D | IA32_PG_A | IA32_PG_U | IA32_PG_RW | IA32_PG_P)
 | |
| //
 | |
| // Bits 1, 2, 5, 6 are reserved in the IA32 PAE PDPTE
 | |
| // X64 PAE PDPTE does not have such restriction
 | |
| //
 | |
| #define IA32_PAE_PDPTE_ATTRIBUTE_BITS    (IA32_PG_P)
 | |
| 
 | |
| #define PAGE_PROGATE_BITS           (IA32_PG_NX | PAGE_ATTRIBUTE_BITS)
 | |
| 
 | |
| #define PAGING_4K_MASK  0xFFF
 | |
| #define PAGING_2M_MASK  0x1FFFFF
 | |
| #define PAGING_1G_MASK  0x3FFFFFFF
 | |
| 
 | |
| #define PAGING_PAE_INDEX_MASK  0x1FF
 | |
| 
 | |
| #define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
 | |
| #define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
 | |
| #define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
 | |
| 
 | |
| #define SMRR_MAX_ADDRESS       BASE_4GB
 | |
| 
 | |
| typedef enum {
 | |
|   PageNone,
 | |
|   Page4K,
 | |
|   Page2M,
 | |
|   Page1G,
 | |
| } PAGE_ATTRIBUTE;
 | |
| 
 | |
| typedef struct {
 | |
|   PAGE_ATTRIBUTE   Attribute;
 | |
|   UINT64           Length;
 | |
|   UINT64           AddressMask;
 | |
| } PAGE_ATTRIBUTE_TABLE;
 | |
| 
 | |
| //
 | |
| // Size of Task-State Segment defined in IA32 Manual
 | |
| //
 | |
| #define TSS_SIZE              104
 | |
| #define EXCEPTION_TSS_SIZE    (TSS_SIZE + 4) // Add 4 bytes SSP
 | |
| #define TSS_X64_IST1_OFFSET   36
 | |
| #define TSS_IA32_CR3_OFFSET   28
 | |
| #define TSS_IA32_ESP_OFFSET   56
 | |
| #define TSS_IA32_SSP_OFFSET   104
 | |
| 
 | |
| #define CR0_WP                BIT16
 | |
| 
 | |
| //
 | |
| // Code select value
 | |
| //
 | |
| #define PROTECT_MODE_CODE_SEGMENT          0x08
 | |
| #define LONG_MODE_CODE_SEGMENT             0x38
 | |
| 
 | |
| //
 | |
| // The size 0x20 must be bigger than
 | |
| // the size of template code of SmmInit. Currently,
 | |
| // the size of SmmInit requires the 0x16 Bytes buffer
 | |
| // at least.
 | |
| //
 | |
| #define BACK_BUF_SIZE  0x20
 | |
| 
 | |
| #define EXCEPTION_VECTOR_NUMBER     0x20
 | |
| 
 | |
| #define INVALID_APIC_ID 0xFFFFFFFFFFFFFFFFULL
 | |
| 
 | |
| typedef UINT32                              SMM_CPU_ARRIVAL_EXCEPTIONS;
 | |
| #define ARRIVAL_EXCEPTION_BLOCKED           0x1
 | |
| #define ARRIVAL_EXCEPTION_DELAYED           0x2
 | |
| #define ARRIVAL_EXCEPTION_SMI_DISABLED      0x4
 | |
| 
 | |
| //
 | |
| // Wrapper used to convert EFI_AP_PROCEDURE2 and EFI_AP_PROCEDURE.
 | |
| //
 | |
| typedef struct {
 | |
|   EFI_AP_PROCEDURE  Procedure;
 | |
|   VOID              *ProcedureArgument;
 | |
| } PROCEDURE_WRAPPER;
 | |
| 
 | |
| #define PROCEDURE_TOKEN_SIGNATURE  SIGNATURE_32 ('P', 'R', 'T', 'S')
 | |
| 
 | |
| typedef struct {
 | |
|   UINTN                   Signature;
 | |
|   LIST_ENTRY              Link;
 | |
| 
 | |
|   SPIN_LOCK               *SpinLock;
 | |
|   volatile UINT32         RunningApCount;
 | |
| } PROCEDURE_TOKEN;
 | |
| 
 | |
| #define PROCEDURE_TOKEN_FROM_LINK(a)  CR (a, PROCEDURE_TOKEN, Link, PROCEDURE_TOKEN_SIGNATURE)
 | |
| 
 | |
| #define TOKEN_BUFFER_SIGNATURE  SIGNATURE_32 ('T', 'K', 'B', 'S')
 | |
| 
 | |
| typedef struct {
 | |
|   UINTN                   Signature;
 | |
|   LIST_ENTRY              Link;
 | |
| 
 | |
|   UINT8                   *Buffer;
 | |
| } TOKEN_BUFFER;
 | |
| 
 | |
| #define TOKEN_BUFFER_FROM_LINK(a)  CR (a, TOKEN_BUFFER, Link, TOKEN_BUFFER_SIGNATURE)
 | |
| 
 | |
| //
 | |
| // Private structure for the SMM CPU module that is stored in DXE Runtime memory
 | |
| // Contains the SMM Configuration Protocols that is produced.
 | |
| // Contains a mix of DXE and SMM contents.  All the fields must be used properly.
 | |
| //
 | |
| #define SMM_CPU_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('s', 'c', 'p', 'u')
 | |
| 
 | |
| typedef struct {
 | |
|   UINTN                           Signature;
 | |
| 
 | |
|   EFI_HANDLE                      SmmCpuHandle;
 | |
| 
 | |
|   EFI_PROCESSOR_INFORMATION       *ProcessorInfo;
 | |
|   SMM_CPU_OPERATION               *Operation;
 | |
|   UINTN                           *CpuSaveStateSize;
 | |
|   VOID                            **CpuSaveState;
 | |
| 
 | |
|   EFI_SMM_RESERVED_SMRAM_REGION   SmmReservedSmramRegion[1];
 | |
|   EFI_SMM_ENTRY_CONTEXT           SmmCoreEntryContext;
 | |
|   EFI_SMM_ENTRY_POINT             SmmCoreEntry;
 | |
| 
 | |
|   EFI_SMM_CONFIGURATION_PROTOCOL  SmmConfiguration;
 | |
| 
 | |
|   PROCEDURE_WRAPPER               *ApWrapperFunc;
 | |
|   LIST_ENTRY                      TokenList;
 | |
|   LIST_ENTRY                      *FirstFreeToken;
 | |
| } SMM_CPU_PRIVATE_DATA;
 | |
| 
 | |
| extern SMM_CPU_PRIVATE_DATA  *gSmmCpuPrivate;
 | |
| extern CPU_HOT_PLUG_DATA      mCpuHotPlugData;
 | |
| extern UINTN                  mMaxNumberOfCpus;
 | |
| extern UINTN                  mNumberOfCpus;
 | |
| extern EFI_SMM_CPU_PROTOCOL   mSmmCpu;
 | |
| extern EFI_MM_MP_PROTOCOL     mSmmMp;
 | |
| extern UINTN                  mInternalCr3;
 | |
| 
 | |
| ///
 | |
| /// The mode of the CPU at the time an SMI occurs
 | |
| ///
 | |
| extern UINT8  mSmmSaveStateRegisterLma;
 | |
| 
 | |
| //
 | |
| // SMM CPU Protocol function prototypes.
 | |
| //
 | |
| 
 | |
| /**
 | |
|   Read information from the CPU save state.
 | |
| 
 | |
|   @param  This      EFI_SMM_CPU_PROTOCOL instance
 | |
|   @param  Width     The number of bytes to read from the CPU save state.
 | |
|   @param  Register  Specifies the CPU register to read form the save state.
 | |
|   @param  CpuIndex  Specifies the zero-based index of the CPU save state
 | |
|   @param  Buffer    Upon return, this holds the CPU register value read from the save state.
 | |
| 
 | |
|   @retval EFI_SUCCESS   The register was read from Save State
 | |
|   @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
 | |
|   @retval EFI_INVALID_PARAMETER   This or Buffer is NULL.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmmReadSaveState (
 | |
|   IN CONST EFI_SMM_CPU_PROTOCOL         *This,
 | |
|   IN UINTN                              Width,
 | |
|   IN EFI_SMM_SAVE_STATE_REGISTER        Register,
 | |
|   IN UINTN                              CpuIndex,
 | |
|   OUT VOID                              *Buffer
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Write data to the CPU save state.
 | |
| 
 | |
|   @param  This      EFI_SMM_CPU_PROTOCOL instance
 | |
|   @param  Width     The number of bytes to read from the CPU save state.
 | |
|   @param  Register  Specifies the CPU register to write to the save state.
 | |
|   @param  CpuIndex  Specifies the zero-based index of the CPU save state
 | |
|   @param  Buffer    Upon entry, this holds the new CPU register value.
 | |
| 
 | |
|   @retval EFI_SUCCESS   The register was written from Save State
 | |
|   @retval EFI_NOT_FOUND The register is not defined for the Save State of Processor
 | |
|   @retval EFI_INVALID_PARAMETER   ProcessorIndex or Width is not correct
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmmWriteSaveState (
 | |
|   IN CONST EFI_SMM_CPU_PROTOCOL         *This,
 | |
|   IN UINTN                              Width,
 | |
|   IN EFI_SMM_SAVE_STATE_REGISTER        Register,
 | |
|   IN UINTN                              CpuIndex,
 | |
|   IN CONST VOID                         *Buffer
 | |
|   );
 | |
| 
 | |
| /**
 | |
| Read a CPU Save State register on the target processor.
 | |
| 
 | |
| This function abstracts the differences that whether the CPU Save State register is in the
 | |
| IA32 CPU Save State Map or X64 CPU Save State Map.
 | |
| 
 | |
| This function supports reading a CPU Save State register in SMBase relocation handler.
 | |
| 
 | |
| @param[in]  CpuIndex       Specifies the zero-based index of the CPU save state.
 | |
| @param[in]  RegisterIndex  Index into mSmmCpuWidthOffset[] look up table.
 | |
| @param[in]  Width          The number of bytes to read from the CPU save state.
 | |
| @param[out] Buffer         Upon return, this holds the CPU register value read from the save state.
 | |
| 
 | |
| @retval EFI_SUCCESS           The register was read from Save State.
 | |
| @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.
 | |
| @retval EFI_INVALID_PARAMETER Buffer is NULL, or Width does not meet requirement per Register type.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| ReadSaveStateRegister (
 | |
|   IN UINTN                        CpuIndex,
 | |
|   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
 | |
|   IN UINTN                        Width,
 | |
|   OUT VOID                        *Buffer
 | |
|   );
 | |
| 
 | |
| /**
 | |
| Write value to a CPU Save State register on the target processor.
 | |
| 
 | |
| This function abstracts the differences that whether the CPU Save State register is in the
 | |
| IA32 CPU Save State Map or X64 CPU Save State Map.
 | |
| 
 | |
| This function supports writing a CPU Save State register in SMBase relocation handler.
 | |
| 
 | |
| @param[in] CpuIndex       Specifies the zero-based index of the CPU save state.
 | |
| @param[in] RegisterIndex  Index into mSmmCpuWidthOffset[] look up table.
 | |
| @param[in] Width          The number of bytes to read from the CPU save state.
 | |
| @param[in] Buffer         Upon entry, this holds the new CPU register value.
 | |
| 
 | |
| @retval EFI_SUCCESS           The register was written to Save State.
 | |
| @retval EFI_NOT_FOUND         The register is not defined for the Save State of Processor.
 | |
| @retval EFI_INVALID_PARAMETER  ProcessorIndex or Width is not correct.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| WriteSaveStateRegister (
 | |
|   IN UINTN                        CpuIndex,
 | |
|   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
 | |
|   IN UINTN                        Width,
 | |
|   IN CONST VOID                   *Buffer
 | |
|   );
 | |
| 
 | |
| extern CONST UINT8                  gcSmmInitTemplate[];
 | |
| extern CONST UINT16                 gcSmmInitSize;
 | |
| X86_ASSEMBLY_PATCH_LABEL            gPatchSmmCr0;
 | |
| extern UINT32                       mSmmCr0;
 | |
| X86_ASSEMBLY_PATCH_LABEL            gPatchSmmCr3;
 | |
| extern UINT32                       mSmmCr4;
 | |
| X86_ASSEMBLY_PATCH_LABEL            gPatchSmmCr4;
 | |
| X86_ASSEMBLY_PATCH_LABEL            gPatchSmmInitStack;
 | |
| X86_ASSEMBLY_PATCH_LABEL            mPatchCetSupported;
 | |
| extern BOOLEAN                      mCetSupported;
 | |
| 
 | |
| /**
 | |
|   Semaphore operation for all processor relocate SMMBase.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SmmRelocationSemaphoreComplete (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| ///
 | |
| /// The type of SMM CPU Information
 | |
| ///
 | |
| typedef struct {
 | |
|   SPIN_LOCK                         *Busy;
 | |
|   volatile EFI_AP_PROCEDURE2        Procedure;
 | |
|   volatile VOID                     *Parameter;
 | |
|   volatile UINT32                   *Run;
 | |
|   volatile BOOLEAN                  *Present;
 | |
|   PROCEDURE_TOKEN                   *Token;
 | |
|   EFI_STATUS                        *Status;
 | |
| } SMM_CPU_DATA_BLOCK;
 | |
| 
 | |
| typedef enum {
 | |
|   SmmCpuSyncModeTradition,
 | |
|   SmmCpuSyncModeRelaxedAp,
 | |
|   SmmCpuSyncModeMax
 | |
| } SMM_CPU_SYNC_MODE;
 | |
| 
 | |
| typedef struct {
 | |
|   //
 | |
|   // Pointer to an array. The array should be located immediately after this structure
 | |
|   // so that UC cache-ability can be set together.
 | |
|   //
 | |
|   SMM_CPU_DATA_BLOCK            *CpuData;
 | |
|   volatile UINT32               *Counter;
 | |
|   volatile UINT32               BspIndex;
 | |
|   volatile BOOLEAN              *InsideSmm;
 | |
|   volatile BOOLEAN              *AllCpusInSync;
 | |
|   volatile SMM_CPU_SYNC_MODE    EffectiveSyncMode;
 | |
|   volatile BOOLEAN              SwitchBsp;
 | |
|   volatile BOOLEAN              *CandidateBsp;
 | |
|   EFI_AP_PROCEDURE              StartupProcedure;
 | |
|   VOID                          *StartupProcArgs;
 | |
| } SMM_DISPATCHER_MP_SYNC_DATA;
 | |
| 
 | |
| #define SMM_PSD_OFFSET              0xfb00
 | |
| 
 | |
| ///
 | |
| /// All global semaphores' pointer
 | |
| ///
 | |
| typedef struct {
 | |
|   volatile UINT32      *Counter;
 | |
|   volatile BOOLEAN     *InsideSmm;
 | |
|   volatile BOOLEAN     *AllCpusInSync;
 | |
|   SPIN_LOCK            *PFLock;
 | |
|   SPIN_LOCK            *CodeAccessCheckLock;
 | |
| } SMM_CPU_SEMAPHORE_GLOBAL;
 | |
| 
 | |
| ///
 | |
| /// All semaphores for each processor
 | |
| ///
 | |
| typedef struct {
 | |
|   SPIN_LOCK                         *Busy;
 | |
|   volatile UINT32                   *Run;
 | |
|   volatile BOOLEAN                  *Present;
 | |
|   SPIN_LOCK                         *Token;
 | |
| } SMM_CPU_SEMAPHORE_CPU;
 | |
| 
 | |
| ///
 | |
| /// All semaphores' information
 | |
| ///
 | |
| typedef struct {
 | |
|   SMM_CPU_SEMAPHORE_GLOBAL          SemaphoreGlobal;
 | |
|   SMM_CPU_SEMAPHORE_CPU             SemaphoreCpu;
 | |
| } SMM_CPU_SEMAPHORES;
 | |
| 
 | |
| extern IA32_DESCRIPTOR                     gcSmiGdtr;
 | |
| extern EFI_PHYSICAL_ADDRESS                mGdtBuffer;
 | |
| extern UINTN                               mGdtBufferSize;
 | |
| extern IA32_DESCRIPTOR                     gcSmiIdtr;
 | |
| extern VOID                                *gcSmiIdtrPtr;
 | |
| extern UINT64                              gPhyMask;
 | |
| extern SMM_DISPATCHER_MP_SYNC_DATA         *mSmmMpSyncData;
 | |
| extern UINTN                               mSmmStackArrayBase;
 | |
| extern UINTN                               mSmmStackArrayEnd;
 | |
| extern UINTN                               mSmmStackSize;
 | |
| extern EFI_SMM_CPU_SERVICE_PROTOCOL        mSmmCpuService;
 | |
| extern IA32_DESCRIPTOR                     gcSmiInitGdtr;
 | |
| extern SMM_CPU_SEMAPHORES                  mSmmCpuSemaphores;
 | |
| extern UINTN                               mSemaphoreSize;
 | |
| extern SPIN_LOCK                           *mPFLock;
 | |
| extern SPIN_LOCK                           *mConfigSmmCodeAccessCheckLock;
 | |
| extern EFI_SMRAM_DESCRIPTOR                *mSmmCpuSmramRanges;
 | |
| extern UINTN                               mSmmCpuSmramRangeCount;
 | |
| extern UINT8                               mPhysicalAddressBits;
 | |
| 
 | |
| //
 | |
| // Copy of the PcdPteMemoryEncryptionAddressOrMask
 | |
| //
 | |
| extern UINT64  mAddressEncMask;
 | |
| 
 | |
| /**
 | |
|   Create 4G PageTable in SMRAM.
 | |
| 
 | |
|   @param[in]      Is32BitPageTable Whether the page table is 32-bit PAE
 | |
|   @return         PageTable Address
 | |
| 
 | |
| **/
 | |
| UINT32
 | |
| Gen4GPageTable (
 | |
|   IN      BOOLEAN                   Is32BitPageTable
 | |
|   );
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Initialize global data for MP synchronization.
 | |
| 
 | |
|   @param Stacks             Base address of SMI stack buffer for all processors.
 | |
|   @param StackSize          Stack size for each processor in SMM.
 | |
|   @param ShadowStackSize    Shadow Stack size for each processor in SMM.
 | |
| 
 | |
| **/
 | |
| UINT32
 | |
| InitializeMpServiceData (
 | |
|   IN VOID        *Stacks,
 | |
|   IN UINTN       StackSize,
 | |
|   IN UINTN       ShadowStackSize
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Initialize Timer for SMM AP Sync.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| InitializeSmmTimer (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Start Timer for SMM AP Sync.
 | |
| 
 | |
| **/
 | |
| UINT64
 | |
| EFIAPI
 | |
| StartSyncTimer (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Check if the SMM AP Sync timer is timeout.
 | |
| 
 | |
|   @param Timer  The start timer from the begin.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| IsSyncTimerTimeout (
 | |
|   IN      UINT64                    Timer
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Initialize IDT for SMM Stack Guard.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| InitializeIDTSmmStackGuard (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Initialize Gdt for all processors.
 | |
| 
 | |
|   @param[in]   Cr3          CR3 value.
 | |
|   @param[out]  GdtStepSize  The step size for GDT table.
 | |
| 
 | |
|   @return GdtBase for processor 0.
 | |
|           GdtBase for processor X is: GdtBase + (GdtStepSize * X)
 | |
| **/
 | |
| VOID *
 | |
| InitGdt (
 | |
|   IN  UINTN  Cr3,
 | |
|   OUT UINTN  *GdtStepSize
 | |
|   );
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Register the SMM Foundation entry point.
 | |
| 
 | |
|   @param          This              Pointer to EFI_SMM_CONFIGURATION_PROTOCOL instance
 | |
|   @param          SmmEntryPoint     SMM Foundation EntryPoint
 | |
| 
 | |
|   @retval         EFI_SUCCESS       Successfully to register SMM foundation entry point
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| RegisterSmmEntry (
 | |
|   IN CONST EFI_SMM_CONFIGURATION_PROTOCOL  *This,
 | |
|   IN EFI_SMM_ENTRY_POINT                   SmmEntryPoint
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Create PageTable for SMM use.
 | |
| 
 | |
|   @return     PageTable Address
 | |
| 
 | |
| **/
 | |
| UINT32
 | |
| SmmInitPageTable (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Schedule a procedure to run on the specified CPU.
 | |
| 
 | |
|   @param   Procedure        The address of the procedure to run
 | |
|   @param   CpuIndex         Target CPU number
 | |
|   @param   ProcArguments    The parameter to pass to the procedure
 | |
| 
 | |
|   @retval   EFI_INVALID_PARAMETER    CpuNumber not valid
 | |
|   @retval   EFI_INVALID_PARAMETER    CpuNumber specifying BSP
 | |
|   @retval   EFI_INVALID_PARAMETER    The AP specified by CpuNumber did not enter SMM
 | |
|   @retval   EFI_INVALID_PARAMETER    The AP specified by CpuNumber is busy
 | |
|   @retval   EFI_SUCCESS - The procedure has been successfully scheduled
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmmStartupThisAp (
 | |
|   IN      EFI_AP_PROCEDURE          Procedure,
 | |
|   IN      UINTN                     CpuIndex,
 | |
|   IN OUT  VOID                      *ProcArguments OPTIONAL
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Schedule a procedure to run on the specified CPU in a blocking fashion.
 | |
| 
 | |
|   @param  Procedure                The address of the procedure to run
 | |
|   @param  CpuIndex                 Target CPU Index
 | |
|   @param  ProcArguments            The parameter to pass to the procedure
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER    CpuNumber not valid
 | |
|   @retval EFI_INVALID_PARAMETER    CpuNumber specifying BSP
 | |
|   @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber did not enter SMM
 | |
|   @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber is busy
 | |
|   @retval EFI_SUCCESS              The procedure has been successfully scheduled
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SmmBlockingStartupThisAp (
 | |
|   IN      EFI_AP_PROCEDURE          Procedure,
 | |
|   IN      UINTN                     CpuIndex,
 | |
|   IN OUT  VOID                      *ProcArguments OPTIONAL
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This function sets the attributes for the memory region specified by BaseAddress and
 | |
|   Length from their current attributes to the attributes specified by Attributes.
 | |
| 
 | |
|   @param[in]  BaseAddress      The physical address that is the start address of a memory region.
 | |
|   @param[in]  Length           The size in bytes of the memory region.
 | |
|   @param[in]  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
 | |
| SmmSetMemoryAttributes (
 | |
|   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
 | |
|   IN  UINT64                                     Length,
 | |
|   IN  UINT64                                     Attributes
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This function clears the attributes for the memory region specified by BaseAddress and
 | |
|   Length from their current attributes to the attributes specified by Attributes.
 | |
| 
 | |
|   @param[in]  BaseAddress      The physical address that is the start address of a memory region.
 | |
|   @param[in]  Length           The size in bytes of the memory region.
 | |
|   @param[in]  Attributes       The bit mask of attributes to clear for the memory region.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The attributes were cleared 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
 | |
| SmmClearMemoryAttributes (
 | |
|   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
 | |
|   IN  UINT64                                     Length,
 | |
|   IN  UINT64                                     Attributes
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Initialize MP synchronization data.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| InitializeMpSyncData (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Find out SMRAM information including SMRR base and SMRR size.
 | |
| 
 | |
|   @param          SmrrBase          SMRR base
 | |
|   @param          SmrrSize          SMRR size
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| FindSmramInfo (
 | |
|   OUT UINT32   *SmrrBase,
 | |
|   OUT UINT32   *SmrrSize
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Relocate SmmBases for each processor.
 | |
| 
 | |
|   Execute on first boot and all S3 resumes
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SmmRelocateBases (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Page Fault handler for SMM use.
 | |
| 
 | |
|   @param  InterruptType    Defines the type of interrupt or exception that
 | |
|                            occurred on the processor.This parameter is processor architecture specific.
 | |
|   @param  SystemContext    A pointer to the processor context when
 | |
|                            the interrupt occurred on the processor.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| SmiPFHandler (
 | |
|   IN EFI_EXCEPTION_TYPE   InterruptType,
 | |
|   IN EFI_SYSTEM_CONTEXT   SystemContext
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Perform the remaining tasks.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| PerformRemainingTasks (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Perform the pre tasks.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| PerformPreTasks (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Initialize MSR spin lock by MSR index.
 | |
| 
 | |
|   @param  MsrIndex       MSR index value.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| InitMsrSpinLockByIndex (
 | |
|   IN UINT32      MsrIndex
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Hook return address of SMM Save State so that semaphore code
 | |
|   can be executed immediately after AP exits SMM to indicate to
 | |
|   the BSP that an AP has exited SMM after SMBASE relocation.
 | |
| 
 | |
|   @param[in] CpuIndex     The processor index.
 | |
|   @param[in] RebasedFlag  A pointer to a flag that is set to TRUE
 | |
|                           immediately after AP exits SMM.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| SemaphoreHook (
 | |
|   IN UINTN             CpuIndex,
 | |
|   IN volatile BOOLEAN  *RebasedFlag
 | |
|   );
 | |
| 
 | |
| /**
 | |
| Configure SMM Code Access Check feature for all processors.
 | |
| SMM Feature Control MSR will be locked after configuration.
 | |
| **/
 | |
| VOID
 | |
| ConfigSmmCodeAccessCheck (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Hook the code executed immediately after an RSM instruction on the currently
 | |
|   executing CPU.  The mode of code executed immediately after RSM must be
 | |
|   detected, and the appropriate hook must be selected.  Always clear the auto
 | |
|   HALT restart flag if it is set.
 | |
| 
 | |
|   @param[in] CpuIndex                 The processor index for the currently
 | |
|                                       executing CPU.
 | |
|   @param[in] CpuState                 Pointer to SMRAM Save State Map for the
 | |
|                                       currently executing CPU.
 | |
|   @param[in] NewInstructionPointer32  Instruction pointer to use if resuming to
 | |
|                                       32-bit mode from 64-bit SMM.
 | |
|   @param[in] NewInstructionPointer    Instruction pointer to use if resuming to
 | |
|                                       same mode as SMM.
 | |
| 
 | |
|   @retval The value of the original instruction pointer before it was hooked.
 | |
| 
 | |
| **/
 | |
| UINT64
 | |
| EFIAPI
 | |
| HookReturnFromSmm (
 | |
|   IN UINTN              CpuIndex,
 | |
|   SMRAM_SAVE_STATE_MAP  *CpuState,
 | |
|   UINT64                NewInstructionPointer32,
 | |
|   UINT64                NewInstructionPointer
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Get the size of the SMI Handler in bytes.
 | |
| 
 | |
|   @retval The size, in bytes, of the SMI Handler.
 | |
| 
 | |
| **/
 | |
| UINTN
 | |
| EFIAPI
 | |
| GetSmiHandlerSize (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Install the SMI handler for the CPU specified by CpuIndex.  This function
 | |
|   is called by the CPU that was elected as monarch during System Management
 | |
|   Mode initialization.
 | |
| 
 | |
|   @param[in] CpuIndex   The index of the CPU to install the custom SMI handler.
 | |
|                         The value must be between 0 and the NumberOfCpus field
 | |
|                         in the System Management System Table (SMST).
 | |
|   @param[in] SmBase     The SMBASE address for the CPU specified by CpuIndex.
 | |
|   @param[in] SmiStack   The stack to use when an SMI is processed by the
 | |
|                         the CPU specified by CpuIndex.
 | |
|   @param[in] StackSize  The size, in bytes, if the stack used when an SMI is
 | |
|                         processed by the CPU specified by CpuIndex.
 | |
|   @param[in] GdtBase    The base address of the GDT to use when an SMI is
 | |
|                         processed by the CPU specified by CpuIndex.
 | |
|   @param[in] GdtSize    The size, in bytes, of the GDT used when an SMI is
 | |
|                         processed by the CPU specified by CpuIndex.
 | |
|   @param[in] IdtBase    The base address of the IDT to use when an SMI is
 | |
|                         processed by the CPU specified by CpuIndex.
 | |
|   @param[in] IdtSize    The size, in bytes, of the IDT used when an SMI is
 | |
|                         processed by the CPU specified by CpuIndex.
 | |
|   @param[in] Cr3        The base address of the page tables to use when an SMI
 | |
|                         is processed by the CPU specified by CpuIndex.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| InstallSmiHandler (
 | |
|   IN UINTN   CpuIndex,
 | |
|   IN UINT32  SmBase,
 | |
|   IN VOID    *SmiStack,
 | |
|   IN UINTN   StackSize,
 | |
|   IN UINTN   GdtBase,
 | |
|   IN UINTN   GdtSize,
 | |
|   IN UINTN   IdtBase,
 | |
|   IN UINTN   IdtSize,
 | |
|   IN UINT32  Cr3
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Search module name by input IP address and output it.
 | |
| 
 | |
|   @param CallerIpAddress   Caller instruction pointer.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DumpModuleInfoByIp (
 | |
|   IN  UINTN              CallerIpAddress
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This function sets memory attribute according to MemoryAttributesTable.
 | |
| **/
 | |
| VOID
 | |
| SetMemMapAttributes (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This function sets UEFI memory attribute according to UEFI memory map.
 | |
| **/
 | |
| VOID
 | |
| SetUefiMemMapAttributes (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Return if the Address is forbidden as SMM communication buffer.
 | |
| 
 | |
|   @param[in] Address the address to be checked
 | |
| 
 | |
|   @return TRUE  The address is forbidden as SMM communication buffer.
 | |
|   @return FALSE The address is allowed as SMM communication buffer.
 | |
| **/
 | |
| BOOLEAN
 | |
| IsSmmCommBufferForbiddenAddress (
 | |
|   IN UINT64  Address
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This function caches the UEFI memory map information.
 | |
| **/
 | |
| VOID
 | |
| GetUefiMemoryMap (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This function sets memory attribute for page table.
 | |
| **/
 | |
| VOID
 | |
| SetPageTableAttributes (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Get page table base address and the depth of the page table.
 | |
| 
 | |
|   @param[out] Base        Page table base address.
 | |
|   @param[out] FiveLevels  TRUE means 5 level paging. FALSE means 4 level paging.
 | |
| **/
 | |
| VOID
 | |
| GetPageTable (
 | |
|   OUT UINTN   *Base,
 | |
|   OUT BOOLEAN *FiveLevels OPTIONAL
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This function sets the attributes for the memory region specified by BaseAddress and
 | |
|   Length from their current attributes to the attributes specified by Attributes.
 | |
| 
 | |
|   @param[in]   BaseAddress      The physical address that is the start address of a memory region.
 | |
|   @param[in]   Length           The size in bytes of the memory region.
 | |
|   @param[in]   Attributes       The bit mask of attributes to set for the memory region.
 | |
|   @param[out]  IsSplitted       TRUE means page table splitted. FALSE means page table not splitted.
 | |
| 
 | |
|   @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
 | |
| SmmSetMemoryAttributesEx (
 | |
|   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
 | |
|   IN  UINT64                                     Length,
 | |
|   IN  UINT64                                     Attributes,
 | |
|   OUT BOOLEAN                                    *IsSplitted  OPTIONAL
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This function clears the attributes for the memory region specified by BaseAddress and
 | |
|   Length from their current attributes to the attributes specified by Attributes.
 | |
| 
 | |
|   @param[in]   BaseAddress      The physical address that is the start address of a memory region.
 | |
|   @param[in]   Length           The size in bytes of the memory region.
 | |
|   @param[in]   Attributes       The bit mask of attributes to clear for the memory region.
 | |
|   @param[out]  IsSplitted       TRUE means page table splitted. FALSE means page table not splitted.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The attributes were cleared 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
 | |
| SmmClearMemoryAttributesEx (
 | |
|   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
 | |
|   IN  UINT64                                     Length,
 | |
|   IN  UINT64                                     Attributes,
 | |
|   OUT BOOLEAN                                    *IsSplitted  OPTIONAL
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This API provides a way to allocate memory for page table.
 | |
| 
 | |
|   This API can be called more once to allocate memory for page tables.
 | |
| 
 | |
|   Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
 | |
|   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
 | |
|   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
 | |
|   returned.
 | |
| 
 | |
|   @param  Pages                 The number of 4 KB pages to allocate.
 | |
| 
 | |
|   @return A pointer to the allocated buffer or NULL if allocation fails.
 | |
| 
 | |
| **/
 | |
| VOID *
 | |
| AllocatePageTableMemory (
 | |
|   IN UINTN           Pages
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Allocate pages for code.
 | |
| 
 | |
|   @param[in]  Pages Number of pages to be allocated.
 | |
| 
 | |
|   @return Allocated memory.
 | |
| **/
 | |
| VOID *
 | |
| AllocateCodePages (
 | |
|   IN UINTN           Pages
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Allocate aligned pages for code.
 | |
| 
 | |
|   @param[in]  Pages                 Number of pages to be allocated.
 | |
|   @param[in]  Alignment             The requested alignment of the allocation.
 | |
|                                     Must be a power of two.
 | |
|                                     If Alignment is zero, then byte alignment is used.
 | |
| 
 | |
|   @return Allocated memory.
 | |
| **/
 | |
| VOID *
 | |
| AllocateAlignedCodePages (
 | |
|   IN UINTN            Pages,
 | |
|   IN UINTN            Alignment
 | |
|   );
 | |
| 
 | |
| 
 | |
| //
 | |
| // S3 related global variable and function prototype.
 | |
| //
 | |
| 
 | |
| extern BOOLEAN                mSmmS3Flag;
 | |
| 
 | |
| /**
 | |
|   Initialize SMM S3 resume state structure used during S3 Resume.
 | |
| 
 | |
|   @param[in] Cr3    The base address of the page tables to use in SMM.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| InitSmmS3ResumeState (
 | |
|   IN UINT32  Cr3
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Get ACPI CPU data.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| GetAcpiCpuData (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Restore SMM Configuration in S3 boot path.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| RestoreSmmConfigurationInS3 (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Get ACPI S3 enable flag.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| GetAcpiS3EnableFlag (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Transfer AP to safe hlt-loop after it finished restore CPU features on S3 patch.
 | |
| 
 | |
|   @param[in] ApHltLoopCode          The address of the safe hlt-loop function.
 | |
|   @param[in] TopOfStack             A pointer to the new stack to use for the ApHltLoopCode.
 | |
|   @param[in] NumberToFinishAddress  Address of Semaphore of APs finish count.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| TransferApToSafeState (
 | |
|   IN UINTN  ApHltLoopCode,
 | |
|   IN UINTN  TopOfStack,
 | |
|   IN UINTN  NumberToFinishAddress
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Set ShadowStack memory.
 | |
| 
 | |
|   @param[in]  Cr3              The page table base address.
 | |
|   @param[in]  BaseAddress      The physical address that is the start address of a memory region.
 | |
|   @param[in]  Length           The size in bytes of the memory region.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The shadow stack memory is set.
 | |
| **/
 | |
| EFI_STATUS
 | |
| SetShadowStack (
 | |
|   IN  UINTN                                      Cr3,
 | |
|   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
 | |
|   IN  UINT64                                     Length
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Set not present memory.
 | |
| 
 | |
|   @param[in]  Cr3              The page table base address.
 | |
|   @param[in]  BaseAddress      The physical address that is the start address of a memory region.
 | |
|   @param[in]  Length           The size in bytes of the memory region.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The not present memory is set.
 | |
| **/
 | |
| EFI_STATUS
 | |
| SetNotPresentPage (
 | |
|   IN  UINTN                                      Cr3,
 | |
|   IN  EFI_PHYSICAL_ADDRESS                       BaseAddress,
 | |
|   IN  UINT64                                     Length
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Initialize the shadow stack related data structure.
 | |
| 
 | |
|   @param CpuIndex     The index of CPU.
 | |
|   @param ShadowStack  The bottom of the shadow stack for this CPU.
 | |
| **/
 | |
| VOID
 | |
| InitShadowStack (
 | |
|   IN UINTN  CpuIndex,
 | |
|   IN VOID   *ShadowStack
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This function set given attributes of the memory region specified by
 | |
|   BaseAddress and Length.
 | |
| 
 | |
|   @param  This              The EDKII_SMM_MEMORY_ATTRIBUTE_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.
 | |
|                                 Attributes specified an illegal combination of
 | |
|                                 attributes that cannot be set together.
 | |
|   @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 supported for
 | |
|                                 the memory resource range specified by
 | |
|                                 BaseAddress and Length.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| EdkiiSmmSetMemoryAttributes (
 | |
|   IN  EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL   *This,
 | |
|   IN  EFI_PHYSICAL_ADDRESS                  BaseAddress,
 | |
|   IN  UINT64                                Length,
 | |
|   IN  UINT64                                Attributes
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This function clears given attributes of the memory region specified by
 | |
|   BaseAddress and Length.
 | |
| 
 | |
|   @param  This              The EDKII_SMM_MEMORY_ATTRIBUTE_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 clear for the memory
 | |
|                             region.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The attributes were cleared for the memory region.
 | |
|   @retval EFI_INVALID_PARAMETER Length is zero.
 | |
|                                 Attributes specified an illegal combination of
 | |
|                                 attributes that cannot be cleared together.
 | |
|   @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 supported for
 | |
|                                 the memory resource range specified by
 | |
|                                 BaseAddress and Length.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| EdkiiSmmClearMemoryAttributes (
 | |
|   IN  EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL   *This,
 | |
|   IN  EFI_PHYSICAL_ADDRESS                  BaseAddress,
 | |
|   IN  UINT64                                Length,
 | |
|   IN  UINT64                                Attributes
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This function retrieves the attributes of the memory region specified by
 | |
|   BaseAddress and Length. If different attributes are got from different part
 | |
|   of the memory region, EFI_NO_MAPPING will be returned.
 | |
| 
 | |
|   @param  This              The EDKII_SMM_MEMORY_ATTRIBUTE_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        Pointer to attributes returned.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The attributes got for the memory region.
 | |
|   @retval EFI_INVALID_PARAMETER Length is zero.
 | |
|                                 Attributes is NULL.
 | |
|   @retval EFI_NO_MAPPING        Attributes are not consistent cross the memory
 | |
|                                 region.
 | |
|   @retval EFI_UNSUPPORTED       The processor does not support one or more
 | |
|                                 bytes of the memory resource range specified
 | |
|                                 by BaseAddress and Length.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| EdkiiSmmGetMemoryAttributes (
 | |
|   IN  EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL   *This,
 | |
|   IN  EFI_PHYSICAL_ADDRESS                  BaseAddress,
 | |
|   IN  UINT64                                Length,
 | |
|   IN  UINT64                                *Attributes
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This function fixes up the address of the global variable or function
 | |
|   referred in SmmInit assembly files to be the absolute address.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| PiSmmCpuSmmInitFixupAddress (
 | |
|  );
 | |
| 
 | |
| /**
 | |
|   This function fixes up the address of the global variable or function
 | |
|   referred in SmiEntry assembly files to be the absolute address.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| PiSmmCpuSmiEntryFixupAddress (
 | |
|  );
 | |
| 
 | |
| /**
 | |
|   This function reads CR2 register when on-demand paging is enabled
 | |
|   for 64 bit and no action for 32 bit.
 | |
| 
 | |
|   @param[out]  *Cr2  Pointer to variable to hold CR2 register value.
 | |
| **/
 | |
| VOID
 | |
| SaveCr2 (
 | |
|   OUT UINTN  *Cr2
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   This function writes into CR2 register when on-demand paging is enabled
 | |
|   for 64 bit and no action for 32 bit.
 | |
| 
 | |
|   @param[in]  Cr2  Value to write into CR2 register.
 | |
| **/
 | |
| VOID
 | |
| RestoreCr2 (
 | |
|   IN UINTN  Cr2
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Schedule a procedure to run on the specified CPU.
 | |
| 
 | |
|   @param[in]       Procedure                The address of the procedure to run
 | |
|   @param[in]       CpuIndex                 Target CPU Index
 | |
|   @param[in,out]   ProcArguments            The parameter to pass to the procedure
 | |
|   @param[in,out]   Token                    This is an optional parameter that allows the caller to execute the
 | |
|                                             procedure in a blocking or non-blocking fashion. If it is NULL the
 | |
|                                             call is blocking, and the call will not return until the AP has
 | |
|                                             completed the procedure. If the token is not NULL, the call will
 | |
|                                             return immediately. The caller can check whether the procedure has
 | |
|                                             completed with CheckOnProcedure or WaitForProcedure.
 | |
|   @param[in]       TimeoutInMicroseconds    Indicates the time limit in microseconds for the APs to finish
 | |
|                                             execution of Procedure, either for blocking or non-blocking mode.
 | |
|                                             Zero means infinity. If the timeout expires before all APs return
 | |
|                                             from Procedure, then Procedure on the failed APs is terminated. If
 | |
|                                             the timeout expires in blocking mode, the call returns EFI_TIMEOUT.
 | |
|                                             If the timeout expires in non-blocking mode, the timeout determined
 | |
|                                             can be through CheckOnProcedure or WaitForProcedure.
 | |
|                                             Note that timeout support is optional. Whether an implementation
 | |
|                                             supports this feature can be determined via the Attributes data
 | |
|                                             member.
 | |
|   @param[in,out]   CpuStatus                This optional pointer may be used to get the status code returned
 | |
|                                             by Procedure when it completes execution on the target AP, or with
 | |
|                                             EFI_TIMEOUT if the Procedure fails to complete within the optional
 | |
|                                             timeout. The implementation will update this variable with
 | |
|                                             EFI_NOT_READY prior to starting Procedure on the target AP.
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER    CpuNumber not valid
 | |
|   @retval EFI_INVALID_PARAMETER    CpuNumber specifying BSP
 | |
|   @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber did not enter SMM
 | |
|   @retval EFI_INVALID_PARAMETER    The AP specified by CpuNumber is busy
 | |
|   @retval EFI_SUCCESS              The procedure has been successfully scheduled
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| InternalSmmStartupThisAp (
 | |
|   IN      EFI_AP_PROCEDURE2              Procedure,
 | |
|   IN      UINTN                          CpuIndex,
 | |
|   IN OUT  VOID                           *ProcArguments OPTIONAL,
 | |
|   IN OUT  MM_COMPLETION                  *Token,
 | |
|   IN      UINTN                          TimeoutInMicroseconds,
 | |
|   IN OUT  EFI_STATUS                     *CpuStatus
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Checks whether the input token is the current used token.
 | |
| 
 | |
|   @param[in]  Token      This parameter describes the token that was passed into DispatchProcedure or
 | |
|                          BroadcastProcedure.
 | |
| 
 | |
|   @retval TRUE           The input token is the current used token.
 | |
|   @retval FALSE          The input token is not the current used token.
 | |
| **/
 | |
| BOOLEAN
 | |
| IsTokenInUse (
 | |
|   IN SPIN_LOCK           *Token
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Checks status of specified AP.
 | |
| 
 | |
|   This function checks whether the specified AP has finished the task assigned
 | |
|   by StartupThisAP(), and whether timeout expires.
 | |
| 
 | |
|   @param[in]  Token             This parameter describes the token that was passed into DispatchProcedure or
 | |
|                                 BroadcastProcedure.
 | |
| 
 | |
|   @retval EFI_SUCCESS           Specified AP has finished task assigned by StartupThisAPs().
 | |
|   @retval EFI_NOT_READY         Specified AP has not finished task and timeout has not expired.
 | |
| **/
 | |
| EFI_STATUS
 | |
| IsApReady (
 | |
|   IN SPIN_LOCK  *Token
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Check whether it is an present AP.
 | |
| 
 | |
|   @param   CpuIndex      The AP index which calls this function.
 | |
| 
 | |
|   @retval  TRUE           It's a present AP.
 | |
|   @retval  TRUE           This is not an AP or it is not present.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsPresentAp (
 | |
|   IN UINTN        CpuIndex
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Worker function to execute a caller provided function on all enabled APs.
 | |
| 
 | |
|   @param[in]     Procedure               A pointer to the function to be run on
 | |
|                                          enabled APs of the system.
 | |
|   @param[in]     TimeoutInMicroseconds   Indicates the time limit in microseconds for
 | |
|                                          APs to return from Procedure, either for
 | |
|                                          blocking or non-blocking mode.
 | |
|   @param[in,out] ProcedureArguments      The parameter passed into Procedure for
 | |
|                                          all APs.
 | |
|   @param[in,out] Token                   This is an optional parameter that allows the caller to execute the
 | |
|                                          procedure in a blocking or non-blocking fashion. If it is NULL the
 | |
|                                          call is blocking, and the call will not return until the AP has
 | |
|                                          completed the procedure. If the token is not NULL, the call will
 | |
|                                          return immediately. The caller can check whether the procedure has
 | |
|                                          completed with CheckOnProcedure or WaitForProcedure.
 | |
|   @param[in,out] CPUStatus               This optional pointer may be used to get the status code returned
 | |
|                                          by Procedure when it completes execution on the target AP, or with
 | |
|                                          EFI_TIMEOUT if the Procedure fails to complete within the optional
 | |
|                                          timeout. The implementation will update this variable with
 | |
|                                          EFI_NOT_READY prior to starting Procedure on the target AP.
 | |
| 
 | |
|   @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 others                  Failed to Startup all APs.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| InternalSmmStartupAllAPs (
 | |
|   IN       EFI_AP_PROCEDURE2             Procedure,
 | |
|   IN       UINTN                         TimeoutInMicroseconds,
 | |
|   IN OUT   VOID                          *ProcedureArguments OPTIONAL,
 | |
|   IN OUT   MM_COMPLETION                 *Token,
 | |
|   IN OUT   EFI_STATUS                    *CPUStatus
 | |
|   );
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Register the SMM Foundation entry point.
 | |
| 
 | |
|   @param[in]      Procedure            A pointer to the code stream to be run on the designated target AP
 | |
|                                        of the system. Type EFI_AP_PROCEDURE is defined below in Volume 2
 | |
|                                        with the related definitions of
 | |
|                                        EFI_MP_SERVICES_PROTOCOL.StartupAllAPs.
 | |
|                                        If caller may pass a value of NULL to deregister any existing
 | |
|                                        startup procedure.
 | |
|   @param[in,out]  ProcedureArguments   Allows the caller to pass a list of parameters to the code that is
 | |
|                                        run by the AP. It is an optional common mailbox between APs and
 | |
|                                        the caller to share information
 | |
| 
 | |
|   @retval EFI_SUCCESS                  The Procedure has been set successfully.
 | |
|   @retval EFI_INVALID_PARAMETER        The Procedure is NULL but ProcedureArguments not NULL.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| RegisterStartupProcedure (
 | |
|   IN     EFI_AP_PROCEDURE    Procedure,
 | |
|   IN OUT VOID                *ProcedureArguments OPTIONAL
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Allocate buffer for SpinLock and Wrapper function buffer.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| InitializeDataForMmMp (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   Return whether access to non-SMRAM is restricted.
 | |
| 
 | |
|   @retval TRUE  Access to non-SMRAM is restricted.
 | |
|   @retval FALSE Access to non-SMRAM is not restricted.
 | |
| **/
 | |
| BOOLEAN
 | |
| IsRestrictedMemoryAccess (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| #endif
 |