mirror of https://github.com/acidanthera/audk.git
1614 lines
52 KiB
C
1614 lines
52 KiB
C
/** @file
|
|
Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
|
|
|
|
Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
|
|
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
|
|
Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#ifndef _CPU_PISMMCPUDXESMM_H_
|
|
#define _CPU_PISMMCPUDXESMM_H_
|
|
|
|
#include <PiSmm.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 <Guid/SmmBaseHob.h>
|
|
#include <Guid/MpInformation2.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/CpuLib.h>
|
|
#include <Library/CpuExceptionHandlerLib.h>
|
|
#include <Library/ReportStatusCodeLib.h>
|
|
#include <Library/SmmCpuFeaturesLib.h>
|
|
#include <Library/PeCoffGetEntryPointLib.h>
|
|
#include <Library/RegisterCpuFeaturesLib.h>
|
|
#include <Library/PerformanceLib.h>
|
|
#include <Library/CpuPageTableLib.h>
|
|
#include <Library/MmSaveStateLib.h>
|
|
#include <Library/SmmCpuSyncLib.h>
|
|
|
|
#include <AcpiCpuData.h>
|
|
#include <CpuHotPlugData.h>
|
|
|
|
#include <Register/Intel/Cpuid.h>
|
|
#include <Register/Intel/Msr.h>
|
|
|
|
#include "CpuService.h"
|
|
#include "SmmProfile.h"
|
|
#include "SmmMpPerf.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
|
|
|
|
//
|
|
// 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 BOOLEAN m5LevelPagingNeeded;
|
|
extern PAGING_MODE mPagingMode;
|
|
extern UINTN mSmmShadowStackSize;
|
|
|
|
///
|
|
/// The mode of the CPU at the time an SMI occurs
|
|
///
|
|
extern UINT8 mSmmSaveStateRegisterLma;
|
|
|
|
#define PAGE_TABLE_POOL_ALIGNMENT BASE_128KB
|
|
#define PAGE_TABLE_POOL_UNIT_SIZE BASE_128KB
|
|
#define PAGE_TABLE_POOL_UNIT_PAGES EFI_SIZE_TO_PAGES (PAGE_TABLE_POOL_UNIT_SIZE)
|
|
#define PAGE_TABLE_POOL_ALIGN_MASK \
|
|
(~(EFI_PHYSICAL_ADDRESS)(PAGE_TABLE_POOL_ALIGNMENT - 1))
|
|
|
|
typedef struct {
|
|
VOID *NextPool;
|
|
UINTN Offset;
|
|
UINTN FreePages;
|
|
} PAGE_TABLE_POOL;
|
|
|
|
/**
|
|
Disable CET.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
DisableCet (
|
|
VOID
|
|
);
|
|
|
|
/**
|
|
Enable CET.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
EnableCet (
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// 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
|
|
);
|
|
|
|
/**
|
|
C function for SMI handler. To change all processor's SMMBase Register.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
SmmInitHandler (
|
|
VOID
|
|
);
|
|
|
|
/**
|
|
Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init.
|
|
|
|
**/
|
|
VOID
|
|
ExecuteFirstSmiInit (
|
|
VOID
|
|
);
|
|
|
|
extern BOOLEAN mSmmRelocated;
|
|
extern volatile BOOLEAN *mSmmInitialized;
|
|
extern UINT32 mBspApicId;
|
|
|
|
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 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 BspIndex;
|
|
volatile BOOLEAN *InsideSmm;
|
|
volatile BOOLEAN *AllCpusInSync;
|
|
volatile SMM_CPU_SYNC_MODE EffectiveSyncMode;
|
|
volatile BOOLEAN SwitchBsp;
|
|
volatile BOOLEAN *CandidateBsp;
|
|
volatile BOOLEAN AllApArrivedWithException;
|
|
EFI_AP_PROCEDURE StartupProcedure;
|
|
VOID *StartupProcArgs;
|
|
SMM_CPU_SYNC_CONTEXT *SyncContext;
|
|
} SMM_DISPATCHER_MP_SYNC_DATA;
|
|
|
|
#define SMM_PSD_OFFSET 0xfb00
|
|
|
|
///
|
|
/// All global semaphores' pointer
|
|
///
|
|
typedef struct {
|
|
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 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;
|
|
extern BOOLEAN mSmmDebugAgentSupport;
|
|
|
|
//
|
|
// 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
|
|
);
|
|
|
|
/**
|
|
Create page table based on input PagingMode and PhysicalAddressBits in smm.
|
|
|
|
@param[in] PagingMode The paging mode.
|
|
@param[in] PhysicalAddressBits The bits of physical address to map.
|
|
|
|
@retval PageTable Address
|
|
|
|
**/
|
|
UINTN
|
|
GenSmmPageTable (
|
|
IN PAGING_MODE PagingMode,
|
|
IN UINT8 PhysicalAddressBits
|
|
);
|
|
|
|
/**
|
|
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 IDT IST Field.
|
|
|
|
@param[in] ExceptionType Exception type.
|
|
@param[in] Ist IST value.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
InitializeIdtIst (
|
|
IN EFI_EXCEPTION_TYPE ExceptionType,
|
|
IN UINT8 Ist
|
|
);
|
|
|
|
/**
|
|
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 modifies the page attributes for the memory region specified by BaseAddress and
|
|
Length from their current attributes to the attributes specified by Attributes.
|
|
|
|
Caller should make sure BaseAddress and Length is at page boundary.
|
|
|
|
@param[in] PageTableBase The page table base.
|
|
@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 modify for the memory region.
|
|
@param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes.
|
|
@param[out] IsModified TRUE means page table modified. FALSE means page table not modified.
|
|
|
|
@retval RETURN_SUCCESS The attributes were modified for the memory region.
|
|
@retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
|
|
BaseAddress and Length cannot be modified.
|
|
@retval RETURN_INVALID_PARAMETER Length is zero.
|
|
Attributes specified an illegal combination of attributes that
|
|
cannot be set together.
|
|
@retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
|
|
the memory resource range.
|
|
@retval RETURN_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.
|
|
**/
|
|
RETURN_STATUS
|
|
ConvertMemoryPageAttributes (
|
|
IN UINTN PageTableBase,
|
|
IN PAGING_MODE PagingMode,
|
|
IN PHYSICAL_ADDRESS BaseAddress,
|
|
IN UINT64 Length,
|
|
IN UINT64 Attributes,
|
|
IN BOOLEAN IsSet,
|
|
OUT BOOLEAN *IsModified 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
|
|
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
|
|
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
|
|
);
|
|
|
|
/**
|
|
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] PageTableBase The page table base.
|
|
@param[in] PagingMode The paging mode.
|
|
@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
|
|
SmmSetMemoryAttributesEx (
|
|
IN UINTN PageTableBase,
|
|
IN PAGING_MODE PagingMode,
|
|
IN 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] PageTableBase The page table base.
|
|
@param[in] PagingMode The paging mode.
|
|
@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 cleared 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 supported for the memory resource
|
|
range specified by BaseAddress and Length.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
SmmClearMemoryAttributesEx (
|
|
IN UINTN PageTableBase,
|
|
IN PAGING_MODE PagingMode,
|
|
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
|
IN UINT64 Length,
|
|
IN UINT64 Attributes
|
|
);
|
|
|
|
/**
|
|
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
|
|
);
|
|
|
|
/**
|
|
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
|
|
);
|
|
|
|
/**
|
|
Initialize PackageBsp Info. Processor specified by mPackageFirstThreadIndex[PackageIndex]
|
|
will do the package-scope register programming. Set default CpuIndex to (UINT32)-1, which
|
|
means not specified yet.
|
|
|
|
**/
|
|
VOID
|
|
InitPackageFirstThreadIndexInfo (
|
|
VOID
|
|
);
|
|
|
|
/**
|
|
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
|
|
);
|
|
|
|
/**
|
|
Choose blocking or non-blocking mode to Wait for all APs.
|
|
|
|
@param[in] This A pointer to the EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL instance.
|
|
@param[in] BlockingMode Blocking or non-blocking mode.
|
|
|
|
@retval EFI_SUCCESS All APs have arrived SMM mode except SMI disabled APs.
|
|
@retval EFI_TIMEOUT There are APs not in SMM mode in given timeout constraint.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SmmCpuRendezvous (
|
|
IN EDKII_SMM_CPU_RENDEZVOUS_PROTOCOL *This,
|
|
IN BOOLEAN BlockingMode
|
|
);
|
|
|
|
/**
|
|
Insure when this function returns, no AP will execute normal mode code before entering SMM, except SMI disabled APs.
|
|
|
|
**/
|
|
VOID
|
|
SmmWaitForApArrival (
|
|
VOID
|
|
);
|
|
|
|
/**
|
|
Write unprotect read-only pages if Cr0.Bits.WP is 1.
|
|
|
|
@param[out] WriteProtect If Cr0.Bits.WP is enabled.
|
|
|
|
**/
|
|
VOID
|
|
SmmWriteUnprotectReadOnlyPage (
|
|
OUT BOOLEAN *WriteProtect
|
|
);
|
|
|
|
/**
|
|
Write protect read-only pages.
|
|
|
|
@param[in] WriteProtect If Cr0.Bits.WP should be enabled.
|
|
|
|
**/
|
|
VOID
|
|
SmmWriteProtectReadOnlyPage (
|
|
IN BOOLEAN WriteProtect
|
|
);
|
|
|
|
///
|
|
/// Define macros to encapsulate the write unprotect/protect
|
|
/// read-only pages.
|
|
/// Below pieces of logic are defined as macros and not functions
|
|
/// because "CET" feature disable & enable must be in the same
|
|
/// function to avoid shadow stack and normal SMI stack mismatch,
|
|
/// thus WRITE_UNPROTECT_RO_PAGES () must be called pair with
|
|
/// WRITE_PROTECT_RO_PAGES () in same function.
|
|
///
|
|
/// @param[in,out] Wp A BOOLEAN variable local to the containing
|
|
/// function, carrying write protection status from
|
|
/// WRITE_UNPROTECT_RO_PAGES() to
|
|
/// WRITE_PROTECT_RO_PAGES().
|
|
///
|
|
/// @param[in,out] Cet A BOOLEAN variable local to the containing
|
|
/// function, carrying control flow integrity
|
|
/// enforcement status from
|
|
/// WRITE_UNPROTECT_RO_PAGES() to
|
|
/// WRITE_PROTECT_RO_PAGES().
|
|
///
|
|
#define WRITE_UNPROTECT_RO_PAGES(Wp, Cet) \
|
|
do { \
|
|
Cet = ((AsmReadCr4 () & CR4_CET_ENABLE) != 0); \
|
|
if (Cet) { \
|
|
DisableCet (); \
|
|
} \
|
|
SmmWriteUnprotectReadOnlyPage (&Wp); \
|
|
} while (FALSE)
|
|
|
|
#define WRITE_PROTECT_RO_PAGES(Wp, Cet) \
|
|
do { \
|
|
SmmWriteProtectReadOnlyPage (Wp); \
|
|
if (Cet) { \
|
|
EnableCet (); \
|
|
} \
|
|
} while (FALSE)
|
|
|
|
#endif
|