mirror of https://github.com/acidanthera/audk.git
1072 lines
33 KiB
C
1072 lines
33 KiB
C
/** @file
|
|
Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
|
|
|
|
Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
|
|
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
|
|
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
|
|
#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 <Guid/AcpiS3Context.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/CacheMaintenanceLib.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/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 <AcpiCpuData.h>
|
|
#include <CpuHotPlugData.h>
|
|
|
|
#include <Register/Cpuid.h>
|
|
#include <Register/Msr.h>
|
|
|
|
#include "CpuService.h"
|
|
#include "SmmProfile.h"
|
|
|
|
//
|
|
// 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 TSS_X64_IST1_OFFSET 36
|
|
#define TSS_IA32_CR3_OFFSET 28
|
|
#define TSS_IA32_ESP_OFFSET 56
|
|
|
|
#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
|
|
|
|
//
|
|
// 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;
|
|
} 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;
|
|
|
|
///
|
|
/// 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_PARAMTER 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_PARAMTER 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_PARAMTER This or Buffer is NULL.
|
|
|
|
**/
|
|
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_PARAMTER 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
|
|
);
|
|
|
|
//
|
|
//
|
|
//
|
|
typedef struct {
|
|
UINT32 Offset;
|
|
UINT16 Segment;
|
|
UINT16 Reserved;
|
|
} IA32_FAR_ADDRESS;
|
|
|
|
extern IA32_FAR_ADDRESS gSmmJmpAddr;
|
|
|
|
extern CONST UINT8 gcSmmInitTemplate[];
|
|
extern CONST UINT16 gcSmmInitSize;
|
|
extern UINT32 gSmmCr0;
|
|
extern UINT32 gSmmCr3;
|
|
extern UINT32 gSmmCr4;
|
|
extern UINTN gSmmInitStack;
|
|
|
|
/**
|
|
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_PROCEDURE Procedure;
|
|
volatile VOID *Parameter;
|
|
volatile UINT32 *Run;
|
|
volatile BOOLEAN *Present;
|
|
} 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;
|
|
} SMM_DISPATCHER_MP_SYNC_DATA;
|
|
|
|
#define MSR_SPIN_LOCK_INIT_NUM 15
|
|
|
|
typedef struct {
|
|
SPIN_LOCK *SpinLock;
|
|
UINT32 MsrIndex;
|
|
} MP_MSR_LOCK;
|
|
|
|
#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;
|
|
SPIN_LOCK *MemoryMappedLock;
|
|
} SMM_CPU_SEMAPHORE_GLOBAL;
|
|
|
|
///
|
|
/// All semaphores for each processor
|
|
///
|
|
typedef struct {
|
|
SPIN_LOCK *Busy;
|
|
volatile UINT32 *Run;
|
|
volatile BOOLEAN *Present;
|
|
} SMM_CPU_SEMAPHORE_CPU;
|
|
|
|
///
|
|
/// All MSRs semaphores' pointer and counter
|
|
///
|
|
typedef struct {
|
|
SPIN_LOCK *Msr;
|
|
UINTN AvailableCounter;
|
|
} SMM_CPU_SEMAPHORE_MSR;
|
|
|
|
///
|
|
/// All semaphores' information
|
|
///
|
|
typedef struct {
|
|
SMM_CPU_SEMAPHORE_GLOBAL SemaphoreGlobal;
|
|
SMM_CPU_SEMAPHORE_CPU SemaphoreCpu;
|
|
SMM_CPU_SEMAPHORE_MSR SemaphoreMsr;
|
|
} 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 SPIN_LOCK *mMemoryMappedLock;
|
|
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.
|
|
|
|
**/
|
|
UINT32
|
|
InitializeMpServiceData (
|
|
IN VOID *Stacks,
|
|
IN UINTN StackSize
|
|
);
|
|
|
|
/**
|
|
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
|
|
);
|
|
|
|
/**
|
|
This function sets GDT/IDT buffer to be RO and XP.
|
|
**/
|
|
VOID
|
|
PatchGdtIdtMap (
|
|
VOID
|
|
);
|
|
|
|
/**
|
|
|
|
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
|
|
);
|
|
|
|
/**
|
|
Return page table base.
|
|
|
|
@return page table base.
|
|
**/
|
|
UINTN
|
|
GetPageTableBase (
|
|
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] 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
|
|
);
|
|
|
|
#endif
|