mirror of https://review.coreboot.org/STM.git
Add STM, bios and test package.
This commit is contained in:
commit
3da9a66044
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,160 @@
|
|||
/** @file
|
||||
Definitions for CPU S3 data.
|
||||
|
||||
Copyright (c) 2013 - 2015, Intel Corporation. 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 _ACPI_CPU_DATA_H_
|
||||
#define _ACPI_CPU_DATA_H_
|
||||
|
||||
//
|
||||
// Register types in register table
|
||||
//
|
||||
typedef enum {
|
||||
Msr,
|
||||
ControlRegister,
|
||||
MemoryMapped,
|
||||
CacheControl
|
||||
} REGISTER_TYPE;
|
||||
|
||||
//
|
||||
// Element of register table entry
|
||||
//
|
||||
typedef struct {
|
||||
REGISTER_TYPE RegisterType;
|
||||
UINT32 Index;
|
||||
UINT8 ValidBitStart;
|
||||
UINT8 ValidBitLength;
|
||||
UINT64 Value;
|
||||
} CPU_REGISTER_TABLE_ENTRY;
|
||||
|
||||
//
|
||||
// Register table definition, including current table length,
|
||||
// allocated size of this table, and pointer to the list of table entries.
|
||||
//
|
||||
typedef struct {
|
||||
//
|
||||
// The number of valid entries in the RegisterTableEntry buffer
|
||||
//
|
||||
UINT32 TableLength;
|
||||
UINT32 NumberBeforeReset;
|
||||
//
|
||||
// The size, in bytes, of the RegisterTableEntry buffer
|
||||
//
|
||||
UINT32 AllocatedSize;
|
||||
//
|
||||
// The initial APIC ID of the CPU this register table applies to
|
||||
//
|
||||
UINT32 InitialApicId;
|
||||
//
|
||||
// Buffer of CPU_REGISTER_TABLE_ENTRY structures. This buffer must be
|
||||
// allocated below 4GB from memory of type EfiACPIMemoryNVS.
|
||||
//
|
||||
CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
|
||||
} CPU_REGISTER_TABLE;
|
||||
|
||||
//
|
||||
// Data structure that is required for ACPI S3 resume. This structure must be
|
||||
// allocated below 4GB from memory of type EfiACPIMemoryNVS. The PCD
|
||||
// PcdCpuS3DataAddress must be set to the physical address where this structure
|
||||
// is allocated
|
||||
//
|
||||
typedef struct {
|
||||
//
|
||||
// Physical address of 4KB buffer allocated below 1MB from memory of type
|
||||
// EfiReservedMemoryType. The buffer is not required to be initialized, but
|
||||
// it is recommended that the buffer be zero-filled. This buffer is used to
|
||||
// wake APs during an ACPI S3 resume.
|
||||
//
|
||||
EFI_PHYSICAL_ADDRESS StartupVector;
|
||||
//
|
||||
// Physical address of structure of type IA32_DESCRIPTOR. This structure must
|
||||
// be allocated below 4GB from memory of type EfiACPIMemoryNVS. The
|
||||
// IA32_DESCRIPTOR structure provides the base address and length of a GDT
|
||||
// The buffer for GDT must also be allocated below 4GB from memory of type
|
||||
// EfiACPIMemoryNVS. The GDT must be filled in with the GDT contents that are
|
||||
// used during an ACPI S3 resume. This is typically the contents of the GDT
|
||||
// used by the boot processor when the platform is booted.
|
||||
//
|
||||
EFI_PHYSICAL_ADDRESS GdtrProfile;
|
||||
//
|
||||
// Physical address of structure of type IA32_DESCRIPTOR. This structure must
|
||||
// be allocated below 4GB from memory of type EfiACPIMemoryNVS. The
|
||||
// IA32_DESCRIPTOR structure provides the base address and length of an IDT.
|
||||
// The buffer for IDT must also be allocated below 4GB from memory of type
|
||||
// EfiACPIMemoryNVS. The IDT must be filled in with the IDT contents that are
|
||||
// used during an ACPI S3 resume. This is typically the contents of the IDT
|
||||
// used by the boot processor when the platform is booted.
|
||||
//
|
||||
EFI_PHYSICAL_ADDRESS IdtrProfile;
|
||||
//
|
||||
// Physical address of a buffer that is used as stacks during ACPI S3 resume.
|
||||
// The total size of this buffer, in bytes, is NumberOfCpus * StackSize. This
|
||||
// structure must be allocated below 4GB from memory of type EfiACPIMemoryNVS.
|
||||
//
|
||||
EFI_PHYSICAL_ADDRESS StackAddress;
|
||||
//
|
||||
// The size, in bytes, of the stack provided to each CPU during ACPI S3 resume.
|
||||
//
|
||||
UINT32 StackSize;
|
||||
//
|
||||
// The number of CPUs. If a platform does not support hot plug CPUs, then
|
||||
// this is the number of CPUs detected when the platform is booted, regardless
|
||||
// of being enabled or disabled. If a platform does support hot plug CPUs,
|
||||
// then this is the maximum number of CPUs that the platform supports.
|
||||
//
|
||||
UINT32 NumberOfCpus;
|
||||
//
|
||||
// Physical address of structure of type MTRR_SETTINGS that contains a copy
|
||||
// of the MTRR settings that are compatible with the MTRR settings used by
|
||||
// the boot processor when the platform was booted. These MTRR settings are
|
||||
// used during an ACPI S3 resume. This structure must be allocated below 4GB
|
||||
// from memory of type EfiACPIMemoryNVS.
|
||||
//
|
||||
EFI_PHYSICAL_ADDRESS MtrrTable;
|
||||
//
|
||||
// Physical address of an array of CPU_REGISTER_TABLE structures, with
|
||||
// NumberOfCpus entries. This array must be allocated below 4GB from memory
|
||||
// of type EfiACPIMemoryNVS. If a register table is not required, then the
|
||||
// TableLength and AllocatedSize fields of CPU_REGISTER_TABLE are set to 0.
|
||||
// If TableLength is > 0, then elements of RegisterTableEntry are used to
|
||||
// initialize the CPU that matches InitialApicId, during an ACPI S3 resume,
|
||||
// before SMBASE relocation is performed.
|
||||
//
|
||||
EFI_PHYSICAL_ADDRESS PreSmmInitRegisterTable;
|
||||
//
|
||||
// Physical address of an array of CPU_REGISTER_TABLE structures, with
|
||||
// NumberOfCpus entries. This array must be allocated below 4GB from memory
|
||||
// of type EfiACPIMemoryNVS. If a register table is not required, then the
|
||||
// TableLength and AllocatedSize fields of CPU_REGISTER_TABLE are set to 0.
|
||||
// If TableLength is > 0, then elements of RegisterTableEntry are used to
|
||||
// initialize the CPU that matches InitialApicId, during an ACPI S3 resume,
|
||||
// after SMBASE relocation is performed.
|
||||
//
|
||||
EFI_PHYSICAL_ADDRESS RegisterTable;
|
||||
//
|
||||
// Physical address of a buffer that contains the machine check handler that
|
||||
// is used during an ACPI S3 Resume. This buffer must be allocated below 4GB
|
||||
// from memory of type EfiACPIMemoryNVS. In order for this machine check
|
||||
// handler to be active on an AP during an ACPI S3 resume, the machine check
|
||||
// vector in the IDT provided by IdtrProfile must be initialized to transfer
|
||||
// control to this physical address.
|
||||
//
|
||||
EFI_PHYSICAL_ADDRESS ApMachineCheckHandlerBase;
|
||||
//
|
||||
// The size, in bytes, of the machine check handler that is used during an
|
||||
// ACPI S3 Resume. If this field is 0, then a machine check handler is not
|
||||
// provided.
|
||||
//
|
||||
UINT32 ApMachineCheckHandlerSize;
|
||||
} ACPI_CPU_DATA;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
/** @file
|
||||
Definition for a structure sharing information for CPU hot plug.
|
||||
|
||||
Copyright (c) 2013 - 2015, Intel Corporation. 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_HOT_PLUG_DATA_H_
|
||||
#define _CPU_HOT_PLUG_DATA_H_
|
||||
|
||||
#define CPU_HOT_PLUG_DATA_REVISION_1 0x00000001
|
||||
|
||||
typedef struct {
|
||||
UINT32 Revision; // Used for version identification for this structure
|
||||
UINT32 ArrayLength; // The entries number of the following ApicId array and SmBase array
|
||||
//
|
||||
// Data required for SMBASE relocation
|
||||
//
|
||||
UINT64 *ApicId; // Pointer to ApicId array
|
||||
UINTN *SmBase; // Pointer to SmBase array
|
||||
UINT32 Reserved;
|
||||
UINT32 SmrrBase;
|
||||
UINT32 SmrrSize;
|
||||
} CPU_HOT_PLUG_DATA;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
/** @file
|
||||
Provides the data format and Name and GUID definition for MsegHob.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. 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 _MSEG_SMRAM_H_
|
||||
#define _MSEG_SMRAM_H_
|
||||
|
||||
#define MSEG_SMRAM_GUID \
|
||||
{ \
|
||||
0x5802bce4, 0xeeee, 0x4e33, { 0xa1, 0x30, 0xeb, 0xad, 0x27, 0xf0, 0xe4, 0x39 } \
|
||||
}
|
||||
|
||||
extern EFI_GUID gMsegSmramGuid;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,416 @@
|
|||
/** @file
|
||||
Library that provides CPU specific functions to support the PiSmmCpuDxeSmm module.
|
||||
|
||||
Copyright (c) 2015 - 2016, Intel Corporation. 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 __SMM_FEATURES_LIB_H__
|
||||
#define __SMM_FEATURES_LIB_H__
|
||||
|
||||
#include <Protocol/MpService.h>
|
||||
#include <Protocol/SmmCpu.h>
|
||||
#include <Register/SmramSaveStateMap.h>
|
||||
#include <CpuHotPlugData.h>
|
||||
|
||||
///
|
||||
/// Enumeration of SMM registers that are accessed using the library functions
|
||||
/// SmmCpuFeaturesIsSmmRegisterSupported (), SmmCpuFeaturesGetSmmRegister (),
|
||||
/// and SmmCpuFeaturesSetSmmRegister ().
|
||||
///
|
||||
typedef enum {
|
||||
///
|
||||
/// Read-write register to provides access to MSR_SMM_FEATURE_CONTROL if the
|
||||
/// CPU supports this MSR.
|
||||
///
|
||||
SmmRegFeatureControl,
|
||||
///
|
||||
/// Read-only register that returns a non-zero value if the CPU is able to
|
||||
/// respond to SMIs.
|
||||
///
|
||||
SmmRegSmmEnable,
|
||||
///
|
||||
/// Read-only register that returns a non-zero value if the CPU is able to
|
||||
/// respond to SMIs, but is busy with other actions that are causing a delay
|
||||
/// in responding to an SMI. This register abstracts access to MSR_SMM_DELAYED
|
||||
/// if the CPU supports this MSR.
|
||||
///
|
||||
SmmRegSmmDelayed,
|
||||
///
|
||||
/// Read-only register that returns a non-zero value if the CPU is able to
|
||||
/// respond to SMIs, but is busy with other actions that are blocking its
|
||||
/// ability to respond to an SMI. This register abstracts access to
|
||||
/// MSR_SMM_BLOCKED if the CPU supports this MSR.
|
||||
///
|
||||
SmmRegSmmBlocked
|
||||
} SMM_REG_NAME;
|
||||
|
||||
/**
|
||||
Called during the very first SMI into System Management Mode to initialize
|
||||
CPU features, including SMBASE, for the currently executing CPU. Since this
|
||||
is the first SMI, the SMRAM Save State Map is at the default address of
|
||||
SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET. The currently executing
|
||||
CPU is specified by CpuIndex and CpuIndex can be used to access information
|
||||
about the currently executing CPU in the ProcessorInfo array and the
|
||||
HotPlugCpuData data structure.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to initialize. The value
|
||||
must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] IsMonarch TRUE if the CpuIndex is the index of the CPU that
|
||||
was elected as monarch during System Management
|
||||
Mode initialization.
|
||||
FALSE if the CpuIndex is not the index of the CPU
|
||||
that was elected as monarch during System
|
||||
Management Mode initialization.
|
||||
@param[in] ProcessorInfo Pointer to an array of EFI_PROCESSOR_INFORMATION
|
||||
structures. ProcessorInfo[CpuIndex] contains the
|
||||
information for the currently executing CPU.
|
||||
@param[in] CpuHotPlugData Pointer to the CPU_HOT_PLUG_DATA structure that
|
||||
contains the ApidId and SmBase arrays.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesInitializeProcessor (
|
||||
IN UINTN CpuIndex,
|
||||
IN BOOLEAN IsMonarch,
|
||||
IN EFI_PROCESSOR_INFORMATION *ProcessorInfo,
|
||||
IN CPU_HOT_PLUG_DATA *CpuHotPlugData
|
||||
);
|
||||
|
||||
/**
|
||||
This function updates the SMRAM save state on the currently executing CPU
|
||||
to resume execution at a specific address after an RSM instruction. This
|
||||
function must evaluate the SMRAM save state to determine the execution mode
|
||||
the RSM instruction resumes and update the resume execution address with
|
||||
either NewInstructionPointer32 or NewInstructionPoint. The auto HALT restart
|
||||
flag in the SMRAM save state must always be cleared. This function returns
|
||||
the value of the instruction pointer from the SMRAM save state that was
|
||||
replaced. If this function returns 0, then the SMRAM save state was not
|
||||
modified.
|
||||
|
||||
This function is called during the very first SMI on each CPU after
|
||||
SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
|
||||
to signal that the SMBASE of each CPU has been updated before the default
|
||||
SMBASE address is used for the first SMI to the next CPU.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to hook. The value
|
||||
must be between 0 and the NumberOfCpus
|
||||
field in the System Management System Table
|
||||
(SMST).
|
||||
@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 execution mode from 64-bit SMM.
|
||||
@param[in] NewInstructionPointer Instruction pointer to use if resuming to
|
||||
same execution mode as SMM.
|
||||
|
||||
@retval 0 This function did modify the SMRAM save state.
|
||||
@retval > 0 The original instruction pointer value from the SMRAM save state
|
||||
before it was replaced.
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
SmmCpuFeaturesHookReturnFromSmm (
|
||||
IN UINTN CpuIndex,
|
||||
IN SMRAM_SAVE_STATE_MAP *CpuState,
|
||||
IN UINT64 NewInstructionPointer32,
|
||||
IN UINT64 NewInstructionPointer
|
||||
);
|
||||
|
||||
/**
|
||||
Hook point in normal execution mode that allows the one CPU that was elected
|
||||
as monarch during System Management Mode initialization to perform additional
|
||||
initialization actions immediately after all of the CPUs have processed their
|
||||
first SMI and called SmmCpuFeaturesInitializeProcessor() relocating SMBASE
|
||||
into a buffer in SMRAM and called SmmCpuFeaturesHookReturnFromSmm().
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesSmmRelocationComplete (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Return the size, in bytes, of a custom SMI Handler in bytes. If 0 is
|
||||
returned, then a custom SMI handler is not provided by this library,
|
||||
and the default SMI handler must be used.
|
||||
|
||||
@retval 0 Use the default SMI handler.
|
||||
@retval > 0 Use the SMI handler installed by SmmCpuFeaturesInstallSmiHandler()
|
||||
The caller is required to allocate enough SMRAM for each CPU to
|
||||
support the size of the custom SMI handler.
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
SmmCpuFeaturesGetSmiHandlerSize (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Return the offset to SMBASE, of a custom native SMI Handler in bytes.
|
||||
If 0 is returned, then a custom SMI handler is not provided by this library,
|
||||
and the default SMI handler must be used.
|
||||
|
||||
@retval 0 Use the default SMI handler.
|
||||
@retval > 0 If STM is enabled, TXT_PROCESSOR_SMM_DESCRIPTOR.SmmSmiHandlerRip
|
||||
is SmiHandlerOffset + SMBASE.
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
SmmCpuFeaturesGetSmiHandlerOffset (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Install a custom SMI handler for the CPU specified by CpuIndex. This function
|
||||
is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size is greater
|
||||
than zero and 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
|
||||
SmmCpuFeaturesInstallSmiHandler (
|
||||
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
|
||||
);
|
||||
|
||||
/**
|
||||
Determines if MTRR registers must be configured to set SMRAM cache-ability
|
||||
when executing in System Management Mode.
|
||||
|
||||
@retval TRUE MTRR registers must be configured to set SMRAM cache-ability.
|
||||
@retval FALSE MTRR registers do not need to be configured to set SMRAM
|
||||
cache-ability.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
SmmCpuFeaturesNeedConfigureMtrrs (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
|
||||
returns TRUE.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesDisableSmrr (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Enable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
|
||||
returns TRUE.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesReenableSmrr (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Processor specific hook point each time a CPU enters System Management Mode.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU that has entered SMM. The value
|
||||
must be between 0 and the NumberOfCpus field in the
|
||||
System Management System Table (SMST).
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesRendezvousEntry (
|
||||
IN UINTN CpuIndex
|
||||
);
|
||||
|
||||
/**
|
||||
Processor specific hook point each time a CPU exits System Management Mode.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU that is exiting SMM. The value must
|
||||
be between 0 and the NumberOfCpus field in the System
|
||||
Management System Table (SMST).
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesRendezvousExit (
|
||||
IN UINTN CpuIndex
|
||||
);
|
||||
|
||||
/**
|
||||
Check to see if an SMM register is supported by a specified CPU.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to check for SMM register support.
|
||||
The value must be between 0 and the NumberOfCpus field
|
||||
in the System Management System Table (SMST).
|
||||
@param[in] RegName Identifies the SMM register to check for support.
|
||||
|
||||
@retval TRUE The SMM register specified by RegName is supported by the CPU
|
||||
specified by CpuIndex.
|
||||
@retval FALSE The SMM register specified by RegName is not supported by the
|
||||
CPU specified by CpuIndex.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
SmmCpuFeaturesIsSmmRegisterSupported (
|
||||
IN UINTN CpuIndex,
|
||||
IN SMM_REG_NAME RegName
|
||||
);
|
||||
|
||||
/**
|
||||
Returns the current value of the SMM register for the specified CPU.
|
||||
If the SMM register is not supported, then 0 is returned.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to read the SMM register. The
|
||||
value must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] RegName Identifies the SMM register to read.
|
||||
|
||||
@return The value of the SMM register specified by RegName from the CPU
|
||||
specified by CpuIndex.
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
SmmCpuFeaturesGetSmmRegister (
|
||||
IN UINTN CpuIndex,
|
||||
IN SMM_REG_NAME RegName
|
||||
);
|
||||
|
||||
/**
|
||||
Sets the value of an SMM register on a specified CPU.
|
||||
If the SMM register is not supported, then no action is performed.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to write the SMM register. The
|
||||
value must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] RegName Identifies the SMM register to write.
|
||||
registers are read-only.
|
||||
@param[in] Value The value to write to the SMM register.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesSetSmmRegister (
|
||||
IN UINTN CpuIndex,
|
||||
IN SMM_REG_NAME RegName,
|
||||
IN UINT64 Value
|
||||
);
|
||||
|
||||
/**
|
||||
Read an SMM Save State register on the target processor. If this function
|
||||
returns EFI_UNSUPPORTED, then the caller is responsible for reading the
|
||||
SMM Save Sate register.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to read the SMM Save State. The
|
||||
value must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] Register The SMM Save State register to read.
|
||||
@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_INVALID_PARAMTER Buffer is NULL.
|
||||
@retval EFI_UNSUPPORTED This function does not support reading Register.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmCpuFeaturesReadSaveStateRegister (
|
||||
IN UINTN CpuIndex,
|
||||
IN EFI_SMM_SAVE_STATE_REGISTER Register,
|
||||
IN UINTN Width,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Writes an SMM Save State register on the target processor. If this function
|
||||
returns EFI_UNSUPPORTED, then the caller is responsible for writing the
|
||||
SMM Save Sate register.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to write the SMM Save State. The
|
||||
value must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] Register The SMM Save State register to write.
|
||||
@param[in] Width The number of bytes to write to 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_INVALID_PARAMTER Buffer is NULL.
|
||||
@retval EFI_UNSUPPORTED This function does not support writing Register.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmCpuFeaturesWriteSaveStateRegister (
|
||||
IN UINTN CpuIndex,
|
||||
IN EFI_SMM_SAVE_STATE_REGISTER Register,
|
||||
IN UINTN Width,
|
||||
IN CONST VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
This function is hook point called after the gEfiSmmReadyToLockProtocolGuid
|
||||
notification is completely processed.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesCompleteSmmReadyToLock (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
This API provides a method for a CPU to allocate a specific region for storing page tables.
|
||||
|
||||
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.
|
||||
|
||||
This function can also return NULL if there is no preference on where the page tables are allocated in SMRAM.
|
||||
|
||||
@param Pages The number of 4 KB pages to allocate.
|
||||
|
||||
@return A pointer to the allocated buffer for page tables.
|
||||
@retval NULL Fail to allocate a specific region for storing page tables,
|
||||
Or there is no preference on where the page tables are allocated in SMRAM.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
EFIAPI
|
||||
SmmCpuFeaturesAllocatePageTableMemory (
|
||||
IN UINTN Pages
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,109 @@
|
|||
/** @file
|
||||
Public include file for the SMM CPU Platform Hook Library.
|
||||
|
||||
Copyright (c) 2010 - 2015, Intel Corporation. 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 __SMM_CPU_PLATFORM_HOOK_LIB_H__
|
||||
#define __SMM_CPU_PLATFORM_HOOK_LIB_H__
|
||||
|
||||
///
|
||||
/// SMM Page Size Type
|
||||
///
|
||||
typedef enum {
|
||||
SmmPageSize4K,
|
||||
SmmPageSize2M,
|
||||
SmmPageSize1G,
|
||||
MaxSmmPageSizeType
|
||||
} SMM_PAGE_SIZE_TYPE;
|
||||
|
||||
/**
|
||||
Checks if platform produces a valid SMI.
|
||||
|
||||
This function checks if platform produces a valid SMI. This function is
|
||||
called at SMM entry to detect if this is a spurious SMI. This function
|
||||
must be implemented in an MP safe way because it is called by multiple CPU
|
||||
threads.
|
||||
|
||||
@retval TRUE There is a valid SMI
|
||||
@retval FALSE There is no valid SMI
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
PlatformValidSmi (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Clears platform top level SMI status bit.
|
||||
|
||||
This function clears platform top level SMI status bit.
|
||||
|
||||
@retval TRUE The platform top level SMI status is cleared.
|
||||
@retval FALSE The platform top level SMI status cannot be cleared.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ClearTopLevelSmiStatus (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Performs platform specific way of SMM BSP election.
|
||||
|
||||
This function performs platform specific way of SMM BSP election.
|
||||
|
||||
@param IsBsp Output parameter. TRUE: the CPU this function executes
|
||||
on is elected to be the SMM BSP. FALSE: the CPU this
|
||||
function executes on is to be SMM AP.
|
||||
|
||||
@retval EFI_SUCCESS The function executes successfully.
|
||||
@retval EFI_NOT_READY The function does not determine whether this CPU should be
|
||||
BSP or AP. This may occur if hardware init sequence to
|
||||
enable the determination is yet to be done, or the function
|
||||
chooses not to do BSP election and will let SMM CPU driver to
|
||||
use its default BSP election process.
|
||||
@retval EFI_DEVICE_ERROR The function cannot determine whether this CPU should be
|
||||
BSP or AP due to hardware error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PlatformSmmBspElection (
|
||||
OUT BOOLEAN *IsBsp
|
||||
);
|
||||
|
||||
/**
|
||||
Get platform page table attribute .
|
||||
|
||||
This function gets page table attribute of platform.
|
||||
|
||||
@param Address Input parameter. Obtain the page table entries attribute on this address.
|
||||
@param PageSize Output parameter. The size of the page.
|
||||
@param NumOfPages Output parameter. Number of page.
|
||||
@param PageAttribute Output parameter. Paging Attributes (WB, UC, etc).
|
||||
|
||||
@retval EFI_SUCCESS The platform page table attribute from the address is determined.
|
||||
@retval EFI_UNSUPPORTED The platform does not support getting page table attribute for the address.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetPlatformPageTableAttribute (
|
||||
IN UINT64 Address,
|
||||
OUT SMM_PAGE_SIZE_TYPE *PageSize,
|
||||
OUT UINTN *NumOfPages,
|
||||
OUT UINTN *PageAttribute
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,141 @@
|
|||
/** @file
|
||||
STM service protocol definition
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. 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 _SM_MONITOR_INIT_PROTOCOL_H_
|
||||
#define _SM_MONITOR_INIT_PROTOCOL_H_
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <StmApi.h>
|
||||
|
||||
#define EFI_SM_MONITOR_INIT_PROTOCOL_GUID \
|
||||
{ 0x228f344d, 0xb3de, 0x43bb, 0xa4, 0xd7, 0xea, 0x20, 0xb, 0x1b, 0x14, 0x82}
|
||||
|
||||
//
|
||||
// STM service
|
||||
//
|
||||
|
||||
/**
|
||||
|
||||
Load STM image to MSEG.
|
||||
|
||||
@param StmImage STM image
|
||||
@param StmImageSize STM image size
|
||||
|
||||
@retval EFI_SUCCESS Load STM to MSEG successfully
|
||||
@retval EFI_ALREADY_STARTED STM image is already loaded to MSEG
|
||||
@retval EFI_BUFFER_TOO_SMALL MSEG is smaller than minimal requirement of STM image
|
||||
@retval EFI_UNSUPPORTED MSEG is not enabled
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_SM_MONITOR_LOAD_MONITOR) (
|
||||
IN EFI_PHYSICAL_ADDRESS StmImage,
|
||||
IN UINTN StmImageSize
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
Add resources in list to database.
|
||||
|
||||
@param ResourceList A pointer to resource list to be added
|
||||
@param NumEntries Optional number of entries.
|
||||
If 0, list must be terminated by END_OF_RESOURCES.
|
||||
|
||||
@retval EFI_SUCCESS If resources are added
|
||||
@retval EFI_INVALID_PARAMETER If nested procedure detected resource failer
|
||||
@retval EFI_OUT_OF_RESOURCES If nested procedure returned it and we cannot allocate more areas.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_SM_MONITOR_ADD_PI_RESOURCE) (
|
||||
IN STM_RSC *ResourceList,
|
||||
IN UINT32 NumEntries OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
Delete resources in list to database.
|
||||
|
||||
@param ResourceList A pointer to resource list to be deleted
|
||||
NULL means delete all resources.
|
||||
@param NumEntries Optional number of entries.
|
||||
If 0, list must be terminated by END_OF_RESOURCES.
|
||||
|
||||
@retval EFI_SUCCESS If resources are deleted
|
||||
@retval EFI_INVALID_PARAMETER If nested procedure detected resource failer
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_SM_MONITOR_DELETE_PI_RESOURCE) (
|
||||
IN STM_RSC *ResourceList OPTIONAL,
|
||||
IN UINT32 NumEntries OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
Get BIOS resources.
|
||||
|
||||
@param ResourceList A pointer to resource list to be filled
|
||||
@param ResourceSize On input it means size of resource list input.
|
||||
On output it means size of resource list filled,
|
||||
or the size of resource list to be filled if size of too small.
|
||||
|
||||
@retval EFI_SUCCESS If resources are returned.
|
||||
@retval EFI_BUFFER_TOO_SMALL If resource list buffer is too small to hold the whole resources.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_SM_MONITOR_GET_PI_RESOURCE) (
|
||||
OUT STM_RSC *ResourceList,
|
||||
IN OUT UINT32 *ResourceSize
|
||||
);
|
||||
|
||||
typedef UINT32 EFI_SM_MONITOR_STATE;
|
||||
#define EFI_SM_MONITOR_STATE_ENABLED 0x1
|
||||
#define EFI_SM_MONITOR_STATE_ACTIVATED 0x2
|
||||
|
||||
/**
|
||||
|
||||
Get STM state
|
||||
|
||||
@return STM state
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_SM_MONITOR_STATE
|
||||
(EFIAPI *EFI_SM_MONITOR_GET_MONITOR_STATE) (
|
||||
VOID
|
||||
);
|
||||
|
||||
typedef struct _EFI_SM_MONITOR_INIT_PROTOCOL {
|
||||
//
|
||||
// Valid at boot-time only
|
||||
//
|
||||
EFI_SM_MONITOR_LOAD_MONITOR LoadMonitor;
|
||||
EFI_SM_MONITOR_ADD_PI_RESOURCE AddPiResource;
|
||||
EFI_SM_MONITOR_DELETE_PI_RESOURCE DeletePiResource;
|
||||
EFI_SM_MONITOR_GET_PI_RESOURCE GetPiResource;
|
||||
//
|
||||
// Valid at runtime
|
||||
//
|
||||
EFI_SM_MONITOR_GET_MONITOR_STATE GetMonitorState;
|
||||
} EFI_SM_MONITOR_INIT_PROTOCOL;
|
||||
|
||||
extern EFI_GUID gEfiSmMonitorInitProtocolGuid;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,209 @@
|
|||
/** @file
|
||||
SMM CPU Service protocol definition.
|
||||
|
||||
Copyright (c) 2013 - 2015, Intel Corporation. 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 _SMM_CPU_SERVICE_PROTOCOL_H_
|
||||
#define _SMM_CPU_SERVICE_PROTOCOL_H_
|
||||
|
||||
//
|
||||
// Share some definitions with MP Services and CPU Arch Protocol
|
||||
//
|
||||
#include <Protocol/MpService.h>
|
||||
#include <Protocol/Cpu.h>
|
||||
|
||||
#define EFI_SMM_CPU_SERVICE_PROTOCOL_GUID \
|
||||
{ \
|
||||
0x1d202cab, 0xc8ab, 0x4d5c, { 0x94, 0xf7, 0x3c, 0xfc, 0xc0, 0xd3, 0xd3, 0x35 } \
|
||||
}
|
||||
|
||||
typedef struct _EFI_SMM_CPU_SERVICE_PROTOCOL EFI_SMM_CPU_SERVICE_PROTOCOL;
|
||||
|
||||
//
|
||||
// Protocol functions
|
||||
//
|
||||
|
||||
/**
|
||||
Gets processor information on the requested processor at the
|
||||
instant this call is made. This service may only be called from the BSP.
|
||||
|
||||
@param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL
|
||||
instance.
|
||||
@param[in] ProcessorNumber The handle number of processor.
|
||||
@param[out] ProcessorInfoBuffer A pointer to the buffer where information for
|
||||
the requested processor is deposited.
|
||||
|
||||
@retval EFI_SUCCESS Processor information was returned.
|
||||
@retval EFI_DEVICE_ERROR The calling processor is an AP.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
|
||||
@retval EFI_NOT_FOUND The processor with the handle specified by
|
||||
ProcessorNumber does not exist in the platform.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI * EFI_SMM_GET_PROCESSOR_INFO) (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN UINTN ProcessorNumber,
|
||||
OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
|
||||
);
|
||||
|
||||
/**
|
||||
This service switches the requested AP to be the BSP from that point onward.
|
||||
This service changes the BSP for all purposes. This call can only be performed
|
||||
by the current BSP.
|
||||
|
||||
This service switches the requested AP to be the BSP from that point onward.
|
||||
This service changes the BSP for all purposes. The new BSP can take over the
|
||||
execution of the old BSP and continue seamlessly from where the old one left
|
||||
off.
|
||||
|
||||
If the BSP cannot be switched prior to the return from this service, then
|
||||
EFI_UNSUPPORTED must be returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param[in] ProcessorNumber The handle number of AP that is to become the new
|
||||
BSP. The range is from 0 to the total number of
|
||||
logical processors minus 1.
|
||||
|
||||
@retval EFI_SUCCESS BSP successfully switched.
|
||||
@retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to
|
||||
this service returning.
|
||||
@retval EFI_UNSUPPORTED Switching the BSP is not supported.
|
||||
@retval EFI_SUCCESS The calling processor is an AP.
|
||||
@retval EFI_NOT_FOUND The processor with the handle specified by
|
||||
ProcessorNumber does not exist.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or
|
||||
a disabled AP.
|
||||
@retval EFI_NOT_READY The specified AP is busy.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI * EFI_SMM_SWITCH_BSP) (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN UINTN ProcessorNumber
|
||||
);
|
||||
|
||||
/**
|
||||
Notify that a new processor has been added to the system.
|
||||
|
||||
The SMM CPU driver should add the processor to the SMM CPU list.
|
||||
|
||||
If the processor is disabled it won't participate any SMI handler during subsequent SMIs.
|
||||
|
||||
@param This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param ProcessorId The hardware ID of the processor.
|
||||
@param ProcessorNumber The handle number of processor.
|
||||
@param ProcessorResource A pointer to EFI_SMM_PROCESSOR_RESOURCE which holds the assigned resources.
|
||||
|
||||
@retval EFI_SUCCESS The function completed successfully.
|
||||
@retval EFI_ALREADY_STARTED Processor already present.
|
||||
@retval EFI_NOT_READY Space for a new handle could not be allocated.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_SMM_ADD_PROCESSOR) (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN UINT64 ProcessorId,
|
||||
OUT UINTN *ProcessorNumber
|
||||
);
|
||||
|
||||
/**
|
||||
Notify that a processor is hot-removed.
|
||||
|
||||
Remove a processor from the CPU list of the SMM CPU driver. After this API is called, the removed processor
|
||||
must not respond to SMIs in the coherence domain.
|
||||
|
||||
@param This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param ProcessorId The hardware ID of the processor.
|
||||
|
||||
@retval EFI_SUCCESS The function completed successfully.
|
||||
@retval EFI_NOT_FOUND Processor with the hardware ID specified by ProcessorId does not exist.
|
||||
@retval EFI_NOT_READY Specified AP is busy.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_SMM_REMOVE_PROCESSOR) (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN UINTN ProcessorNumber
|
||||
);
|
||||
|
||||
/**
|
||||
This return the handle number for the calling processor. This service may be
|
||||
called from the BSP and APs.
|
||||
|
||||
This service returns the processor handle number for the calling processor.
|
||||
The returned value is in the range from 0 to the total number of logical
|
||||
processors minus 1. This service may be called from the BSP and APs.
|
||||
If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER
|
||||
is returned. Otherwise, the current processors handle number is returned in
|
||||
ProcessorNumber, and EFI_SUCCESS is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param[in] ProcessorNumber The handle number of AP that is to become the new
|
||||
BSP. The range is from 0 to the total number of
|
||||
logical processors minus 1.
|
||||
|
||||
@retval EFI_SUCCESS The current processor handle number was returned
|
||||
in ProcessorNumber.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI * EFI_SMM_WHOAMI) (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
OUT UINTN *ProcessorNumber
|
||||
);
|
||||
|
||||
/**
|
||||
Register exception handler.
|
||||
|
||||
@param This A pointer to the SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param ExceptionType Defines which interrupt or exception to hook. Type EFI_EXCEPTION_TYPE and
|
||||
the valid values for this parameter are defined in EFI_DEBUG_SUPPORT_PROTOCOL
|
||||
of the UEFI 2.0 specification.
|
||||
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
|
||||
that is called when a processor interrupt occurs.
|
||||
If this parameter is NULL, then the handler will be uninstalled.
|
||||
|
||||
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
|
||||
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was previously installed.
|
||||
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not previously installed.
|
||||
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EFI_SMM_REGISTER_EXCEPTION_HANDLER) (
|
||||
IN EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN EFI_EXCEPTION_TYPE ExceptionType,
|
||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
|
||||
);
|
||||
|
||||
//
|
||||
// This protocol provides CPU services from SMM.
|
||||
//
|
||||
struct _EFI_SMM_CPU_SERVICE_PROTOCOL {
|
||||
EFI_SMM_GET_PROCESSOR_INFO GetProcessorInfo;
|
||||
EFI_SMM_SWITCH_BSP SwitchBsp;
|
||||
EFI_SMM_ADD_PROCESSOR AddProcessor;
|
||||
EFI_SMM_REMOVE_PROCESSOR RemoveProcessor;
|
||||
EFI_SMM_WHOAMI WhoAmI;
|
||||
EFI_SMM_REGISTER_EXCEPTION_HANDLER RegisterExceptionHandler;
|
||||
};
|
||||
|
||||
extern EFI_GUID gEfiSmmCpuServiceProtocolGuid;
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,190 @@
|
|||
/** @file
|
||||
SMRAM Save State Map Definitions.
|
||||
|
||||
SMRAM Save State Map definitions based on contents of the
|
||||
Intel(R) 64 and IA-32 Architectures Software Developer's Manual
|
||||
Volume 3C, Section 34.4 SMRAM
|
||||
Volume 3C, Section 34.5 SMI Handler Execution Environment
|
||||
Volume 3C, Section 34.7 Managing Synchronous and Asynchronous SMIs
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. 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 __SMRAM_SAVE_STATE_MAP_H__
|
||||
#define __SMRAM_SAVE_STATE_MAP_H__
|
||||
|
||||
///
|
||||
/// Default SMBASE address
|
||||
///
|
||||
#define SMM_DEFAULT_SMBASE 0x30000
|
||||
|
||||
///
|
||||
/// Offset of SMM handler from SMBASE
|
||||
///
|
||||
#define SMM_HANDLER_OFFSET 0x8000
|
||||
|
||||
///
|
||||
/// Offset of SMRAM Save State Map from SMBASE
|
||||
///
|
||||
#define SMRAM_SAVE_STATE_MAP_OFFSET 0xfc00
|
||||
|
||||
#pragma pack (1)
|
||||
|
||||
///
|
||||
/// 32-bit SMRAM Save State Map
|
||||
///
|
||||
typedef struct {
|
||||
UINT8 Reserved[0x200]; // 7c00h
|
||||
// Padded an extra 0x200 bytes so 32-bit and 64-bit
|
||||
// SMRAM Save State Maps are the same size
|
||||
UINT8 Reserved1[0xf8]; // 7e00h
|
||||
UINT32 SMBASE; // 7ef8h
|
||||
UINT32 SMMRevId; // 7efch
|
||||
UINT16 IORestart; // 7f00h
|
||||
UINT16 AutoHALTRestart; // 7f02h
|
||||
UINT8 Reserved2[0x9C]; // 7f08h
|
||||
UINT32 IOMemAddr; // 7fa0h
|
||||
UINT32 IOMisc; // 7fa4h
|
||||
UINT32 _ES; // 7fa8h
|
||||
UINT32 _CS; // 7fach
|
||||
UINT32 _SS; // 7fb0h
|
||||
UINT32 _DS; // 7fb4h
|
||||
UINT32 _FS; // 7fb8h
|
||||
UINT32 _GS; // 7fbch
|
||||
UINT32 Reserved3; // 7fc0h
|
||||
UINT32 _TR; // 7fc4h
|
||||
UINT32 _DR7; // 7fc8h
|
||||
UINT32 _DR6; // 7fcch
|
||||
UINT32 _EAX; // 7fd0h
|
||||
UINT32 _ECX; // 7fd4h
|
||||
UINT32 _EDX; // 7fd8h
|
||||
UINT32 _EBX; // 7fdch
|
||||
UINT32 _ESP; // 7fe0h
|
||||
UINT32 _EBP; // 7fe4h
|
||||
UINT32 _ESI; // 7fe8h
|
||||
UINT32 _EDI; // 7fech
|
||||
UINT32 _EIP; // 7ff0h
|
||||
UINT32 _EFLAGS; // 7ff4h
|
||||
UINT32 _CR3; // 7ff8h
|
||||
UINT32 _CR0; // 7ffch
|
||||
} SMRAM_SAVE_STATE_MAP32;
|
||||
|
||||
///
|
||||
/// 64-bit SMRAM Save State Map
|
||||
///
|
||||
typedef struct {
|
||||
UINT8 Reserved1[0x1d0]; // 7c00h
|
||||
UINT32 GdtBaseHiDword; // 7dd0h
|
||||
UINT32 LdtBaseHiDword; // 7dd4h
|
||||
UINT32 IdtBaseHiDword; // 7dd8h
|
||||
UINT8 Reserved2[0xc]; // 7ddch
|
||||
UINT64 IO_EIP; // 7de8h
|
||||
UINT8 Reserved3[0x50]; // 7df0h
|
||||
UINT32 _CR4; // 7e40h
|
||||
UINT8 Reserved4[0x48]; // 7e44h
|
||||
UINT32 GdtBaseLoDword; // 7e8ch
|
||||
UINT32 Reserved5; // 7e90h
|
||||
UINT32 IdtBaseLoDword; // 7e94h
|
||||
UINT32 Reserved6; // 7e98h
|
||||
UINT32 LdtBaseLoDword; // 7e9ch
|
||||
UINT8 Reserved7[0x38]; // 7ea0h
|
||||
UINT64 EptVmxControl; // 7ed8h
|
||||
UINT32 EnEptVmxControl; // 7ee0h
|
||||
UINT8 Reserved8[0x14]; // 7ee4h
|
||||
UINT32 SMBASE; // 7ef8h
|
||||
UINT32 SMMRevId; // 7efch
|
||||
UINT16 IORestart; // 7f00h
|
||||
UINT16 AutoHALTRestart; // 7f02h
|
||||
UINT8 Reserved9[0x18]; // 7f04h
|
||||
UINT64 _R15; // 7f1ch
|
||||
UINT64 _R14;
|
||||
UINT64 _R13;
|
||||
UINT64 _R12;
|
||||
UINT64 _R11;
|
||||
UINT64 _R10;
|
||||
UINT64 _R9;
|
||||
UINT64 _R8;
|
||||
UINT64 _RAX; // 7f5ch
|
||||
UINT64 _RCX;
|
||||
UINT64 _RDX;
|
||||
UINT64 _RBX;
|
||||
UINT64 _RSP;
|
||||
UINT64 _RBP;
|
||||
UINT64 _RSI;
|
||||
UINT64 _RDI;
|
||||
UINT64 IOMemAddr; // 7f9ch
|
||||
UINT32 IOMisc; // 7fa4h
|
||||
UINT32 _ES; // 7fa8h
|
||||
UINT32 _CS;
|
||||
UINT32 _SS;
|
||||
UINT32 _DS;
|
||||
UINT32 _FS;
|
||||
UINT32 _GS;
|
||||
UINT32 _LDTR; // 7fc0h
|
||||
UINT32 _TR;
|
||||
UINT64 _DR7; // 7fc8h
|
||||
UINT64 _DR6;
|
||||
UINT64 _RIP; // 7fd8h
|
||||
UINT64 IA32_EFER; // 7fe0h
|
||||
UINT64 _RFLAGS; // 7fe8h
|
||||
UINT64 _CR3; // 7ff0h
|
||||
UINT64 _CR0; // 7ff8h
|
||||
} SMRAM_SAVE_STATE_MAP64;
|
||||
|
||||
///
|
||||
/// Union of 32-bit and 64-bit SMRAM Save State Maps
|
||||
///
|
||||
typedef union {
|
||||
SMRAM_SAVE_STATE_MAP32 x86;
|
||||
SMRAM_SAVE_STATE_MAP64 x64;
|
||||
} SMRAM_SAVE_STATE_MAP;
|
||||
|
||||
///
|
||||
/// Minimum SMM Revision ID that supports IOMisc field in SMRAM Save State Map
|
||||
///
|
||||
#define SMRAM_SAVE_STATE_MIN_REV_ID_IOMISC 0x30004
|
||||
|
||||
///
|
||||
/// SMRAM Save State Map IOMisc I/O Length Values
|
||||
///
|
||||
#define SMM_IO_LENGTH_BYTE 0x01
|
||||
#define SMM_IO_LENGTH_WORD 0x02
|
||||
#define SMM_IO_LENGTH_DWORD 0x04
|
||||
|
||||
///
|
||||
/// SMRAM Save State Map IOMisc I/O Instruction Type Values
|
||||
///
|
||||
#define SMM_IO_TYPE_IN_IMMEDIATE 0x9
|
||||
#define SMM_IO_TYPE_IN_DX 0x1
|
||||
#define SMM_IO_TYPE_OUT_IMMEDIATE 0x8
|
||||
#define SMM_IO_TYPE_OUT_DX 0x0
|
||||
#define SMM_IO_TYPE_INS 0x3
|
||||
#define SMM_IO_TYPE_OUTS 0x2
|
||||
#define SMM_IO_TYPE_REP_INS 0x7
|
||||
#define SMM_IO_TYPE_REP_OUTS 0x6
|
||||
|
||||
///
|
||||
/// SMRAM Save State Map IOMisc structure
|
||||
///
|
||||
typedef union {
|
||||
struct {
|
||||
UINT32 SmiFlag:1;
|
||||
UINT32 Length:3;
|
||||
UINT32 Type:4;
|
||||
UINT32 Reserved1:8;
|
||||
UINT32 Port:16;
|
||||
} Bits;
|
||||
UINT32 Uint32;
|
||||
} SMRAM_SAVE_STATE_IOMISC;
|
||||
|
||||
#pragma pack ()
|
||||
|
||||
#endif
|
|
@ -0,0 +1,732 @@
|
|||
/** @file
|
||||
STM API definition
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. 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 _STM_API_H_
|
||||
#define _STM_API_H_
|
||||
|
||||
// definition in STM spec
|
||||
|
||||
#define STM_SPEC_VERSION_MAJOR 1
|
||||
#define STM_SPEC_VERSION_MINOR 0
|
||||
|
||||
#pragma pack (push, 1)
|
||||
|
||||
#define STM_HARDWARE_FIELD_FILL_TO_2K (2048 - sizeof(UINT32) * 8)
|
||||
typedef struct {
|
||||
UINT32 StmHeaderRevision;
|
||||
UINT32 MonitorFeatures;
|
||||
UINT32 GdtrLimit;
|
||||
UINT32 GdtrBaseOffset;
|
||||
UINT32 CsSelector;
|
||||
UINT32 EipOffset;
|
||||
UINT32 EspOffset;
|
||||
UINT32 Cr3Offset;
|
||||
UINT8 Reserved[STM_HARDWARE_FIELD_FILL_TO_2K];
|
||||
} HARDWARE_STM_HEADER;
|
||||
|
||||
#define STM_FEATURES_IA32E 0x1
|
||||
|
||||
typedef struct {
|
||||
UINT32 Intel64ModeSupported :1; // bitfield
|
||||
UINT32 EptSupported :1; // bitfield
|
||||
UINT32 Reserved :30; // must be 0
|
||||
} STM_FEAT;
|
||||
|
||||
typedef struct {
|
||||
UINT8 StmSpecVerMajor;
|
||||
UINT8 StmSpecVerMinor;
|
||||
UINT16 Reserved; // must be zero
|
||||
UINT32 StaticImageSize;
|
||||
UINT32 PerProcDynamicMemorySize;
|
||||
UINT32 AdditionalDynamicMemorySize;
|
||||
STM_FEAT StmFeatures;
|
||||
UINT32 NumberOfRevIDs;
|
||||
UINT32 StmSmmRevID[1];
|
||||
//
|
||||
// The total STM_HEADER should be 4K.
|
||||
//
|
||||
} SOFTWARE_STM_HEADER;
|
||||
|
||||
typedef struct {
|
||||
HARDWARE_STM_HEADER HwStmHdr;
|
||||
SOFTWARE_STM_HEADER SwStmHdr;
|
||||
} STM_HEADER;
|
||||
|
||||
#define SHA1 1
|
||||
#define SHA256 2
|
||||
typedef struct {
|
||||
UINT64 BiosComponentBase;
|
||||
UINT32 ImageSize;
|
||||
UINT32 HashAlgorithm; // SHA1 or SHA256
|
||||
UINT8 Hash[32];
|
||||
} TXT_BIOS_COMPONENT_STATUS;
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
typedef struct {
|
||||
UINT32 ImageSize;
|
||||
UINT32 Reserved;
|
||||
UINT64 ImagePageBase[1]; //[NumberOfPages];
|
||||
} TXT_BIOS_COMPONENT_UPDATE;
|
||||
|
||||
// If (ImageSizeInBytes % PAGE_SIZE == 0) {
|
||||
// NumberOfPages = ImageSizeInBytes / PAGE_SIZE
|
||||
// } else {
|
||||
// NumberOfPages = ImageSizeInBytes / PAGE_SIZE + 1
|
||||
// }
|
||||
|
||||
|
||||
typedef struct {
|
||||
UINT64 SpeRip;
|
||||
UINT64 SpeRsp;
|
||||
UINT16 SpeSs;
|
||||
UINT16 PageViolationException:1;
|
||||
UINT16 MsrViolationException:1;
|
||||
UINT16 RegisterViolationException:1;
|
||||
UINT16 IoViolationException:1;
|
||||
UINT16 PciViolationException:1;
|
||||
UINT16 Reserved1:11;
|
||||
UINT32 Reserved2;
|
||||
} STM_PROTECTION_EXCEPTION_HANDLER;
|
||||
|
||||
typedef struct {
|
||||
UINT8 ExecutionDisableOutsideSmrr:1;
|
||||
UINT8 Intel64Mode:1;
|
||||
UINT8 Cr4Pae : 1;
|
||||
UINT8 Cr4Pse : 1;
|
||||
UINT8 Reserved1 : 4;
|
||||
} STM_SMM_ENTRY_STATE;
|
||||
|
||||
typedef struct {
|
||||
UINT8 SmramToVmcsRestoreRequired : 1; // BIOS restore hint
|
||||
UINT8 ReinitializeVmcsRequired : 1; // BIOS request
|
||||
UINT8 Reserved2 : 6;
|
||||
} STM_SMM_RESUME_STATE;
|
||||
|
||||
typedef struct {
|
||||
UINT8 DomainType : 4; // STM input to BIOS on each SMI
|
||||
UINT8 XStatePolicy : 2; // STM input to BIOS on each SMI
|
||||
UINT8 EptEnabled : 1;
|
||||
UINT8 Reserved3 : 1;
|
||||
} STM_SMM_STATE;
|
||||
|
||||
typedef struct {
|
||||
UINT64 Signature;
|
||||
UINT16 Size;
|
||||
UINT8 SmmDescriptorVerMajor;
|
||||
UINT8 SmmDescriptorVerMinor;
|
||||
UINT32 LocalApicId;
|
||||
STM_SMM_ENTRY_STATE SmmEntryState;
|
||||
STM_SMM_RESUME_STATE SmmResumeState;
|
||||
STM_SMM_STATE StmSmmState;
|
||||
UINT8 Reserved4;
|
||||
UINT16 SmmCs;
|
||||
UINT16 SmmDs;
|
||||
UINT16 SmmSs;
|
||||
UINT16 SmmOtherSegment;
|
||||
UINT16 SmmTr;
|
||||
UINT16 Reserved5;
|
||||
UINT64 SmmCr3;
|
||||
UINT64 SmmStmSetupRip;
|
||||
UINT64 SmmStmTeardownRip;
|
||||
UINT64 SmmSmiHandlerRip;
|
||||
UINT64 SmmSmiHandlerRsp;
|
||||
UINT64 SmmGdtPtr;
|
||||
UINT32 SmmGdtSize;
|
||||
UINT32 RequiredStmSmmRevId;
|
||||
STM_PROTECTION_EXCEPTION_HANDLER StmProtectionExceptionHandler;
|
||||
UINT64 Reserved6;
|
||||
UINT64 BiosHwResourceRequirementsPtr;
|
||||
// extend area
|
||||
UINT64 AcpiRsdp;
|
||||
UINT8 PhysicalAddressBits;
|
||||
} TXT_PROCESSOR_SMM_DESCRIPTOR;
|
||||
|
||||
#define TXT_PROCESSOR_SMM_DESCRIPTOR_SIGNATURE SIGNATURE_64('T', 'X', 'T', 'P', 'S', 'S', 'I', 'G')
|
||||
#define TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MAJOR 1
|
||||
#define TXT_PROCESSOR_SMM_DESCRIPTOR_VERSION_MINOR 0
|
||||
|
||||
typedef enum {
|
||||
TxtSmmPageViolation = 1,
|
||||
TxtSmmMsrViolation,
|
||||
TxtSmmRegisterViolation,
|
||||
TxtSmmIoViolation,
|
||||
TxtSmmPciViolation
|
||||
} TXT_SMM_PROTECTION_EXCEPTION_TYPE;
|
||||
|
||||
typedef struct {
|
||||
UINT32 Rdi;
|
||||
UINT32 Rsi;
|
||||
UINT32 Rbp;
|
||||
UINT32 Rdx;
|
||||
UINT32 Rcx;
|
||||
UINT32 Rbx;
|
||||
UINT32 Rax;
|
||||
UINT32 Cr3;
|
||||
UINT32 Cr2;
|
||||
UINT32 Cr0;
|
||||
UINT32 VmcsExitInstructionInfo;
|
||||
UINT32 VmcsExitInstructionLength;
|
||||
UINT64 VmcsExitQualification;
|
||||
UINT32 ErrorCode; // TXT_SMM_PROTECTION_EXCEPTION_TYPE
|
||||
UINT32 Rip;
|
||||
UINT32 Cs;
|
||||
UINT32 Rflags;
|
||||
UINT32 Rsp;
|
||||
UINT32 Ss;
|
||||
} STM_PROTECTION_EXCEPTION_STACK_FRAME_IA32;
|
||||
|
||||
typedef struct {
|
||||
UINT64 R15;
|
||||
UINT64 R14;
|
||||
UINT64 R13;
|
||||
UINT64 R12;
|
||||
UINT64 R11;
|
||||
UINT64 R10;
|
||||
UINT64 R9;
|
||||
UINT64 R8;
|
||||
UINT64 Rdi;
|
||||
UINT64 Rsi;
|
||||
UINT64 Rbp;
|
||||
UINT64 Rdx;
|
||||
UINT64 Rcx;
|
||||
UINT64 Rbx;
|
||||
UINT64 Rax;
|
||||
UINT64 Cr8;
|
||||
UINT64 Cr3;
|
||||
UINT64 Cr2;
|
||||
UINT64 Cr0;
|
||||
UINT64 VmcsExitInstructionInfo;
|
||||
UINT64 VmcsExitInstructionLength;
|
||||
UINT64 VmcsExitQualification;
|
||||
UINT64 ErrorCode; // TXT_SMM_PROTECTION_EXCEPTION_TYPE
|
||||
UINT64 Rip;
|
||||
UINT64 Cs;
|
||||
UINT64 Rflags;
|
||||
UINT64 Rsp;
|
||||
UINT64 Ss;
|
||||
} STM_PROTECTION_EXCEPTION_STACK_FRAME_X64;
|
||||
|
||||
typedef union {
|
||||
STM_PROTECTION_EXCEPTION_STACK_FRAME_IA32 *Ia32StackFrame;
|
||||
STM_PROTECTION_EXCEPTION_STACK_FRAME_X64 *X64StackFrame;
|
||||
} STM_PROTECTION_EXCEPTION_STACK_FRAME;
|
||||
|
||||
#define STM_SMM_REV_ID 0x80010100
|
||||
|
||||
typedef struct _STM_SMM_CPU_STATE {
|
||||
UINT8 Reserved1[0x1d0]; // fc00h
|
||||
UINT32 GdtBaseHiDword; // fdd0h : NO
|
||||
UINT32 LdtBaseHiDword; // fdd4h : NO
|
||||
UINT32 IdtBaseHiDword; // fdd8h : NO
|
||||
UINT8 Reserved2[0x4]; // fddch
|
||||
UINT64 IoRdi; // fde0h : NO - restricted
|
||||
UINT64 IoEip; // fde8h : YES
|
||||
UINT64 IoRcx; // fdf0h : NO - restricted
|
||||
UINT64 IoRsi; // fdf8h : NO - restricted
|
||||
UINT8 Reserved3[0x40]; // fe00h
|
||||
UINT32 Cr4; // fe40h : NO
|
||||
UINT8 Reserved4[0x48]; // fe44h
|
||||
UINT32 GdtBaseLoDword; // fe8ch : NO
|
||||
UINT32 GdtLimit; // fe90h : NO - RESTRICTED
|
||||
UINT32 IdtBaseLoDword; // fe94h : NO
|
||||
UINT32 IdtLimit; // fe98h : NO - RESTRICTED
|
||||
UINT32 LdtBaseLoDword; // fe9ch : NO
|
||||
UINT32 LdtLimit; // fea0h : NO - RESTRICTED
|
||||
UINT32 LdtInfo; // fea4h : NO - RESTRICTED
|
||||
UINT8 Reserved5[0x30]; // fea8h
|
||||
UINT64 Eptp; // fed8h : NO
|
||||
UINT32 EnabledEPT; // fee0h : NO
|
||||
UINT8 Reserved6[0x14]; // fee4h
|
||||
UINT32 Smbase; // fef8h : YES - NO for STM
|
||||
UINT32 SMMRevId; // fefch : NO
|
||||
UINT16 IORestart; // ff00h : YES
|
||||
UINT16 AutoHALTRestart; // ff02h : YES
|
||||
UINT8 Reserved7[0x18]; // ff04h
|
||||
UINT64 R15; // ff1ch : YES
|
||||
UINT64 R14; // ff24h : YES
|
||||
UINT64 R13; // ff2ch : YES
|
||||
UINT64 R12; // ff34h : YES
|
||||
UINT64 R11; // ff3ch : YES
|
||||
UINT64 R10; // ff44h : YES
|
||||
UINT64 R9; // ff4ch : YES
|
||||
UINT64 R8; // ff54h : YES
|
||||
UINT64 Rax; // ff5ch : YES
|
||||
UINT64 Rcx; // ff64h : YES
|
||||
UINT64 Rdx; // ff6ch : YES
|
||||
UINT64 Rbx; // ff74h : YES
|
||||
UINT64 Rsp; // ff7ch : YES
|
||||
UINT64 Rbp; // ff84h : YES
|
||||
UINT64 Rsi; // ff8ch : YES
|
||||
UINT64 Rdi; // ff94h : YES
|
||||
UINT64 IOMemAddr; // ff9ch : NO
|
||||
UINT32 IOMisc; // ffa4h : NO
|
||||
UINT32 Es; // ffa8h : NO
|
||||
UINT32 Cs; // ffach : NO
|
||||
UINT32 Ss; // ffb0h : NO
|
||||
UINT32 Ds; // ffb4h : NO
|
||||
UINT32 Fs; // ffb8h : NO
|
||||
UINT32 Gs; // ffbch : NO
|
||||
UINT32 Ldtr; // ffc0h : NO
|
||||
UINT32 Tr; // ffc4h : NO
|
||||
UINT64 Dr7; // ffc8h : NO
|
||||
UINT64 Dr6; // ffd0h : NO
|
||||
UINT64 Rip; // ffd8h : YES
|
||||
UINT64 Ia32Efer; // ffe0h : YES - NO for STM
|
||||
UINT64 Rflags; // ffe8h : YES
|
||||
UINT64 Cr3; // fff0h : NO
|
||||
UINT64 Cr0; // fff8h : NO
|
||||
} STM_SMM_CPU_STATE;
|
||||
|
||||
//
|
||||
// STM Mapping
|
||||
//
|
||||
|
||||
typedef struct {
|
||||
UINT64 PhysicalAddress;
|
||||
UINT64 VirtualAddress;
|
||||
UINT32 PageCount;
|
||||
UINT32 PatCacheType;
|
||||
} STM_MAP_ADDRESS_RANGE_DESCRIPTOR;
|
||||
#define ST_UC 0x00
|
||||
#define WC 0x01
|
||||
#define WT 0x04
|
||||
#define WP 0x05
|
||||
#define WB 0x06
|
||||
#define UC 0x07
|
||||
#define FOLLOW_MTRR 0xFFFFFFFF
|
||||
|
||||
typedef struct {
|
||||
UINT64 VirtualAddress;
|
||||
UINT32 Length;
|
||||
} STM_UNMAP_ADDRESS_RANGE_DESCRIPTOR;
|
||||
|
||||
typedef struct {
|
||||
UINT64 InterruptedGuestVirtualAddress;
|
||||
UINT32 Length;
|
||||
UINT64 InterruptedCr3;
|
||||
UINT64 InterruptedEptp;
|
||||
UINT32 MapToSmmGuest:2;
|
||||
UINT32 InterruptedCr4Pae:1;
|
||||
UINT32 InterruptedCr4Pse:1;
|
||||
UINT32 InterruptedIa32eMode:1;
|
||||
UINT32 Reserved1:27;
|
||||
UINT32 Reserved2;
|
||||
UINT64 PhysicalAddress;
|
||||
UINT64 SmmGuestVirtualAddress;
|
||||
} STM_ADDRESS_LOOKUP_DESCRIPTOR;
|
||||
#define DO_NOT_MAP 0
|
||||
#define ONE_TO_ONE 1
|
||||
#define VIRTUAL_ADDRESS_SPECIFIED 3
|
||||
|
||||
//
|
||||
// STM_RESOURCE_LIST
|
||||
//
|
||||
#define END_OF_RESOURCES 0
|
||||
#define MEM_RANGE 1
|
||||
#define IO_RANGE 2
|
||||
#define MMIO_RANGE 3
|
||||
#define MACHINE_SPECIFIC_REG 4
|
||||
#define PCI_CFG_RANGE 5
|
||||
#define TRAPPED_IO_RANGE 6
|
||||
#define ALL_RESOURCES 7
|
||||
#define REGISTER_VIOLATION 8
|
||||
#define MAX_DESC_TYPE 8
|
||||
|
||||
typedef struct {
|
||||
UINT32 RscType;
|
||||
UINT16 Length;
|
||||
UINT16 ReturnStatus:1;
|
||||
UINT16 Reserved:14;
|
||||
UINT16 IgnoreResource:1;
|
||||
} STM_RSC_DESC_HEADER;
|
||||
|
||||
typedef struct {
|
||||
STM_RSC_DESC_HEADER Hdr;
|
||||
UINT64 ResourceListContinuation;
|
||||
} STM_RSC_END;
|
||||
|
||||
// byte granular Memory range support
|
||||
#define STM_RSC_BGM 0x4
|
||||
|
||||
typedef struct {
|
||||
STM_RSC_DESC_HEADER Hdr;
|
||||
UINT64 Base;
|
||||
UINT64 Length;
|
||||
UINT32 RWXAttributes:3;
|
||||
UINT32 Reserved:29;
|
||||
UINT32 Reserved_2;
|
||||
} STM_RSC_MEM_DESC;
|
||||
#define STM_RSC_MEM_R 0x1
|
||||
#define STM_RSC_MEM_W 0x2
|
||||
#define STM_RSC_MEM_X 0x4
|
||||
|
||||
typedef struct {
|
||||
STM_RSC_DESC_HEADER Hdr;
|
||||
UINT16 Base;
|
||||
UINT16 Length;
|
||||
UINT32 Reserved;
|
||||
} STM_RSC_IO_DESC;
|
||||
|
||||
// byte granular MMIO range support
|
||||
#define STM_RSC_BGI 0x2
|
||||
|
||||
typedef struct {
|
||||
STM_RSC_DESC_HEADER Hdr;
|
||||
UINT64 Base;
|
||||
UINT64 Length;
|
||||
UINT32 RWXAttributes:3;
|
||||
UINT32 Reserved:29;
|
||||
UINT32 Reserved_2;
|
||||
} STM_RSC_MMIO_DESC;
|
||||
#define STM_RSC_MMIO_R 0x1
|
||||
#define STM_RSC_MMIO_W 0x2
|
||||
#define STM_RSC_MMIO_X 0x4
|
||||
|
||||
typedef struct {
|
||||
STM_RSC_DESC_HEADER Hdr;
|
||||
UINT32 MsrIndex;
|
||||
UINT32 KernelModeProcessing:1;
|
||||
UINT32 Reserved:31;
|
||||
UINT64 ReadMask;
|
||||
UINT64 WriteMask;
|
||||
} STM_RSC_MSR_DESC;
|
||||
|
||||
// bit granular MSR resource support
|
||||
#define STM_RSC_MSR 0x8
|
||||
|
||||
typedef struct {
|
||||
UINT8 Type; // must be 1, indicating Hardware Device Path
|
||||
UINT8 Subtype; // must be 1, indicating PCI
|
||||
UINT16 Length; // sizeof(STM_PCI_DEVICE_PATH_NODE) which is 6
|
||||
UINT8 PciFunction;
|
||||
UINT8 PciDevice;
|
||||
} STM_PCI_DEVICE_PATH_NODE;
|
||||
typedef struct {
|
||||
STM_RSC_DESC_HEADER Hdr;
|
||||
UINT16 RWAttributes:2;
|
||||
UINT16 Reserved:14;
|
||||
UINT16 Base;
|
||||
UINT16 Length;
|
||||
UINT8 OriginatingBusNumber;
|
||||
UINT8 LastNodeIndex;
|
||||
STM_PCI_DEVICE_PATH_NODE PciDevicePath[1];
|
||||
//STM_PCI_DEVICE_PATH_NODE PciDevicePath[LastNodeIndex + 1];
|
||||
} STM_RSC_PCI_CFG_DESC;
|
||||
|
||||
#define STM_RSC_PCI_CFG_R 0x1
|
||||
#define STM_RSC_PCI_CFG_W 0x2
|
||||
|
||||
typedef struct {
|
||||
STM_RSC_DESC_HEADER Hdr;
|
||||
UINT16 Base;
|
||||
UINT16 Length;
|
||||
UINT16 In:1;
|
||||
UINT16 Out:1;
|
||||
UINT16 Api:1;
|
||||
UINT16 Reserved1:13;
|
||||
UINT16 Reserved2;
|
||||
} STM_RSC_TRAPPED_IO_DESC;
|
||||
|
||||
typedef struct {
|
||||
STM_RSC_DESC_HEADER Hdr;
|
||||
} STM_RSC_ALL_RESOURCES_DESC;
|
||||
|
||||
typedef struct {
|
||||
STM_RSC_DESC_HEADER Hdr;
|
||||
UINT32 RegisterType;
|
||||
UINT32 Reserved;
|
||||
UINT64 ReadMask;
|
||||
UINT64 WriteMask;
|
||||
} STM_REGISTER_VIOLATION_DESC;
|
||||
|
||||
typedef enum {
|
||||
StmRegisterCr0,
|
||||
StmRegisterCr2,
|
||||
StmRegisterCr3,
|
||||
StmRegisterCr4,
|
||||
StmRegisterCr8,
|
||||
StmRegisterMax,
|
||||
} STM_REGISTER_VIOLATION_TYPE;
|
||||
|
||||
typedef union {
|
||||
STM_RSC_DESC_HEADER Header;
|
||||
STM_RSC_END End;
|
||||
STM_RSC_MEM_DESC Mem;
|
||||
STM_RSC_IO_DESC Io;
|
||||
STM_RSC_MMIO_DESC Mmio;
|
||||
STM_RSC_MSR_DESC Msr;
|
||||
STM_RSC_PCI_CFG_DESC PciCfg;
|
||||
STM_RSC_TRAPPED_IO_DESC TrappedIo;
|
||||
STM_RSC_ALL_RESOURCES_DESC All;
|
||||
STM_REGISTER_VIOLATION_DESC RegisterViolation;
|
||||
} STM_RSC;
|
||||
|
||||
//
|
||||
// VMCS database
|
||||
//
|
||||
#define STM_VMCS_DATABASE_REQUEST_ADD 1
|
||||
#define STM_VMCS_DATABASE_REQUEST_REMOVE 0
|
||||
|
||||
// Values for DomainType
|
||||
// Intepreter of DomainType
|
||||
#define DOMAIN_DISALLOWED_IO_OUT (1u << 0)
|
||||
#define DOMAIN_DISALLOWED_IO_IN (1u << 1)
|
||||
#define DOMAIN_INTEGRITY (1u << 2)
|
||||
#define DOMAIN_CONFIDENTIALITY (1u << 3)
|
||||
|
||||
#define DOMAIN_UNPROTECTED 0x00
|
||||
#define DOMAIN_INTEGRITY_PROT_OUT_IN (DOMAIN_INTEGRITY)
|
||||
//#define DOMAIN_INTEGRITY_PROT_OUT (DOMAIN_INTEGRITY | DOMAIN_DISALLOWED_IO_IN)
|
||||
#define DOMAIN_FULLY_PROT_OUT_IN (DOMAIN_CONFIDENTIALITY | DOMAIN_INTEGRITY)
|
||||
//#define DOMAIN_FULLY_PROT_IN (DOMAIN_CONFIDENTIALITY | DOMAIN_INTEGRITY | DOMAIN_DISALLOWED_IO_OUT)
|
||||
//#define DOMAIN_FULLY_PROT_OUT (DOMAIN_CONFIDENTIALITY | DOMAIN_INTEGRITY | DOMAIN_DISALLOWED_IO_IN)
|
||||
#define DOMAIN_FULLY_PROT (DOMAIN_CONFIDENTIALITY | DOMAIN_INTEGRITY | DOMAIN_DISALLOWED_IO_IN | DOMAIN_DISALLOWED_IO_OUT)
|
||||
|
||||
// Values for XStatePolicy
|
||||
#define XSTATE_READWRITE 0x00
|
||||
#define XSTATE_READONLY 0x01
|
||||
#define XSTATE_SCRUB 0x03
|
||||
|
||||
typedef struct {
|
||||
UINT64 VmcsPhysPointer; // bits 11:0 are reserved and must be 0
|
||||
UINT32 DomainType :4;
|
||||
UINT32 XStatePolicy :2;
|
||||
UINT32 DegradationPolicy :4;
|
||||
UINT32 Reserved1 :22; // Must be 0
|
||||
UINT32 AddOrRemove;
|
||||
} STM_VMCS_DATABASE_REQUEST;
|
||||
|
||||
//
|
||||
// Event log
|
||||
//
|
||||
#define NEW_LOG 1
|
||||
#define CONFIGURE_LOG 2
|
||||
#define START_LOG 3
|
||||
#define STOP_LOG 4
|
||||
#define CLEAR_LOG 5
|
||||
#define DELETE_LOG 6
|
||||
typedef enum {
|
||||
EvtLogStarted,
|
||||
EvtLogStopped,
|
||||
EvtLogInvalidParameterDetected,
|
||||
EvtHandledProtectionException,
|
||||
// unhandled protection exceptions result in reset & cannot be logged
|
||||
EvtBiosAccessToUnclaimedResource,
|
||||
EvtMleResourceProtectionGranted,
|
||||
EvtMleResourceProtectionDenied,
|
||||
EvtMleResourceUnprotect,
|
||||
EvtMleResourceUnprotectError,
|
||||
EvtMleDomainTypeDegraded,
|
||||
// add more here
|
||||
EvtMleMax,
|
||||
// Not used
|
||||
EvtInvalid = 0xFFFFFFFF,
|
||||
} EVENT_TYPE;
|
||||
|
||||
//#define STM_EVENT_LOG_PAGE_COUNT_MAX 62
|
||||
|
||||
typedef struct {
|
||||
UINT32 PageCount;
|
||||
UINT64 Pages[1]; // number of elements is PageCount
|
||||
} STM_EVENT_LOG_MANAGEMENT_REQUEST_DATA_LOG_BUFFER;
|
||||
|
||||
typedef union {
|
||||
STM_EVENT_LOG_MANAGEMENT_REQUEST_DATA_LOG_BUFFER LogBuffer;
|
||||
UINT32 EventEnableBitmap; // bitmap of EVENT_TYPE
|
||||
} STM_EVENT_LOG_MANAGEMENT_REQUEST_DATA;
|
||||
|
||||
typedef struct {
|
||||
UINT32 SubFunctionIndex;
|
||||
STM_EVENT_LOG_MANAGEMENT_REQUEST_DATA Data;
|
||||
} STM_EVENT_LOG_MANAGEMENT_REQUEST;
|
||||
|
||||
//
|
||||
// VMCALL API Numbers
|
||||
//
|
||||
|
||||
// API number convention: BIOS facing VMCALL interfaces have bit 16 clear
|
||||
#define STM_API_MAP_ADDRESS_RANGE 0x00000001
|
||||
#define STM_API_UNMAP_ADDRESS_RANGE 0x00000002
|
||||
#define STM_API_ADDRESS_LOOKUP 0x00000003
|
||||
#define STM_API_RETURN_FROM_PROTECTION_EXCEPTION 0x00000004
|
||||
|
||||
// API number convention: MLE facing VMCALL interfaces have bit 16 set
|
||||
//
|
||||
// The STM configuration lifecycle is as follows:
|
||||
// 1. SENTER->SINIT->MLE: MLE begins execution with SMI disabled (masked).
|
||||
// 2. MLE invokes InitializeProtectionVMCALL() to prepare STM for setup of initial protection profile. This is done on a single CPU and has global effect.
|
||||
// 3. MLE invokes ProtectResourceVMCALL() to define the initial protection profile. The protection profile is global across all CPUs.
|
||||
// 4. MLE invokes StartStmVMCALL() to enable the STM to begin receiving SMI events. This must be done on every logical CPU.
|
||||
// 5. MLE may invoke ProtectResourceVMCALL() or UnProtectResourceVMCALL() during runtime as many times as necessary.
|
||||
// 6. MLE invokes StopStmVMCALL() to disable the STM. SMI is again masked following StopStmVMCALL().
|
||||
//
|
||||
#define STM_API_START 0x00010001
|
||||
#define STM_API_STOP 0x00010002
|
||||
#define STM_API_PROTECT_RESOURCE 0x00010003
|
||||
#define STM_API_UNPROTECT_RESOURCE 0x00010004
|
||||
#define STM_API_GET_BIOS_RESOURCES 0x00010005
|
||||
#define STM_API_MANAGE_VMCS_DATABASE 0x00010006
|
||||
#define STM_API_INITIALIZE_PROTECTION 0x00010007
|
||||
#define STM_API_MANAGE_EVENT_LOG 0x00010008
|
||||
|
||||
//
|
||||
// Return codes
|
||||
//
|
||||
typedef UINT32 STM_STATUS;
|
||||
|
||||
#define STM_SUCCESS 0x00000000
|
||||
#define SMM_SUCCESS 0x00000000
|
||||
// all error codes have bit 31 set
|
||||
// STM errors have bit 16 set
|
||||
#define ERROR_STM_SECURITY_VIOLATION 0x80010001
|
||||
#define ERROR_STM_CACHE_TYPE_NOT_SUPPORTED 0x80010002
|
||||
#define ERROR_STM_PAGE_NOT_FOUND 0x80010003
|
||||
#define ERROR_STM_BAD_CR3 0x80010004
|
||||
#define ERROR_STM_PHYSICAL_OVER_4G 0x80010005
|
||||
#define ERROR_STM_VIRTUAL_SPACE_TOO_SMALL 0x80010006
|
||||
#define ERROR_STM_UNPROTECTABLE_RESOURCE 0x80010007
|
||||
#define ERROR_STM_ALREADY_STARTED 0x80010008
|
||||
#define ERROR_STM_WITHOUT_SMX_UNSUPPORTED 0x80010009
|
||||
#define ERROR_STM_STOPPED 0x8001000A
|
||||
#define ERROR_STM_BUFFER_TOO_SMALL 0x8001000B
|
||||
#define ERROR_STM_INVALID_VMCS_DATABASE 0x8001000C
|
||||
#define ERROR_STM_MALFORMED_RESOURCE_LIST 0x8001000D
|
||||
#define ERROR_STM_INVALID_PAGECOUNT 0x8001000E
|
||||
#define ERROR_STM_LOG_ALLOCATED 0x8001000F
|
||||
#define ERROR_STM_LOG_NOT_ALLOCATED 0x80010010
|
||||
#define ERROR_STM_LOG_NOT_STOPPED 0x80010011
|
||||
#define ERROR_STM_LOG_NOT_STARTED 0x80010012
|
||||
#define ERROR_STM_RESERVED_BIT_SET 0x80010013
|
||||
#define ERROR_STM_NO_EVENTS_ENABLED 0x80010014
|
||||
#define ERROR_STM_OUT_OF_RESOURCES 0x80010015
|
||||
#define ERROR_STM_FUNCTION_NOT_SUPPORTED 0x80010016
|
||||
#define ERROR_STM_UNPROTECTABLE 0x80010017
|
||||
#define ERROR_STM_UNSUPPORTED_MSR_BIT 0x80010018
|
||||
#define ERROR_STM_UNSPECIFIED 0x8001FFFF
|
||||
|
||||
// SMM errors have bit 17 set
|
||||
#define ERROR_SMM_BAD_BUFFER 0x80020001
|
||||
#define ERROR_SMM_INVALID_RSC 0x80020004
|
||||
#define ERROR_SMM_INVALID_BUFFER_SIZE 0x80020005
|
||||
#define ERROR_SMM_BUFFER_TOO_SHORT 0x80020006
|
||||
#define ERROR_SMM_INVALID_LIST 0x80020007
|
||||
#define ERROR_SMM_OUT_OF_MEMORY 0x80020008
|
||||
#define ERROR_SMM_AFTER_INIT 0x80020009
|
||||
#define ERROR_SMM_UNSPECIFIED 0x8002FFFF
|
||||
|
||||
// Errors that apply to both have bits 15, 16, and 17 set
|
||||
#define ERROR_INVALID_API 0x80038001
|
||||
#define ERROR_INVALID_PARAMETER 0x80038002
|
||||
|
||||
//
|
||||
// STM TXT.ERRORCODE codes
|
||||
//
|
||||
#define STM_CRASH_PROTECTION_EXCEPTION 0xC000F001
|
||||
#define STM_CRASH_PROTECTION_EXCEPTION_FAILURE 0xC000F002
|
||||
#define STM_CRASH_DOMAIN_DEGRADATION_FAILURE 0xC000F003
|
||||
#define STM_CRASH_BIOS_PANIC 0xC000E000
|
||||
|
||||
typedef struct {
|
||||
UINT32 EventSerialNumber;
|
||||
UINT16 Type;
|
||||
UINT16 Lock :1;
|
||||
UINT16 Valid :1;
|
||||
UINT16 ReadByMle :1;
|
||||
UINT16 Wrapped :1;
|
||||
UINT16 Reserved :12;
|
||||
} LOG_ENTRY_HEADER;
|
||||
|
||||
typedef struct {
|
||||
UINT32 Reserved;
|
||||
} ENTRY_EVT_LOG_STARTED;
|
||||
|
||||
typedef struct {
|
||||
UINT32 Reserved;
|
||||
} ENTRY_EVT_LOG_STOPPED;
|
||||
|
||||
typedef struct {
|
||||
UINT32 VmcallApiNumber;
|
||||
} ENTRY_EVT_LOG_INVALID_PARAM;
|
||||
|
||||
typedef struct {
|
||||
STM_RSC Resource;
|
||||
} ENTRY_EVT_LOG_HANDLED_PROTECTION_EXCEPTION;
|
||||
|
||||
typedef struct {
|
||||
STM_RSC Resource;
|
||||
} ENTRY_EVT_BIOS_ACCESS_UNCLAIMED_RSC;
|
||||
|
||||
typedef struct {
|
||||
STM_RSC Resource;
|
||||
} ENTRY_EVT_MLE_RSC_PROT_GRANTED;
|
||||
|
||||
typedef struct {
|
||||
STM_RSC Resource;
|
||||
} ENTRY_EVT_MLE_RSC_PROT_DENIED;
|
||||
|
||||
typedef struct {
|
||||
STM_RSC Resource;
|
||||
} ENTRY_EVT_MLE_RSC_UNPROT;
|
||||
|
||||
typedef struct {
|
||||
STM_RSC Resource;
|
||||
} ENTRY_EVT_MLE_RSC_UNPROT_ERROR;
|
||||
|
||||
typedef struct {
|
||||
UINT64 VmcsPhysPointer;
|
||||
UINT8 ExpectedDomainType;
|
||||
UINT8 DegradedDomainType;
|
||||
} ENTRY_EVT_MLE_DOMAIN_TYPE_DEGRADED;
|
||||
|
||||
typedef union {
|
||||
ENTRY_EVT_LOG_STARTED Started;
|
||||
ENTRY_EVT_LOG_STOPPED Stopped;
|
||||
ENTRY_EVT_LOG_INVALID_PARAM InvalidParam;
|
||||
ENTRY_EVT_LOG_HANDLED_PROTECTION_EXCEPTION HandledProtectionException;
|
||||
ENTRY_EVT_BIOS_ACCESS_UNCLAIMED_RSC BiosUnclaimedRsc;
|
||||
ENTRY_EVT_MLE_RSC_PROT_GRANTED MleRscProtGranted;
|
||||
ENTRY_EVT_MLE_RSC_PROT_DENIED MleRscProtDenied;
|
||||
ENTRY_EVT_MLE_RSC_UNPROT MleRscUnprot;
|
||||
ENTRY_EVT_MLE_RSC_UNPROT_ERROR MleRscUnprotError;
|
||||
ENTRY_EVT_MLE_DOMAIN_TYPE_DEGRADED MleDomainTypeDegraded;
|
||||
} LOG_ENTRY_DATA;
|
||||
|
||||
typedef struct {
|
||||
LOG_ENTRY_HEADER Hdr;
|
||||
LOG_ENTRY_DATA Data;
|
||||
} STM_LOG_ENTRY;
|
||||
|
||||
#define STM_LOG_ENTRY_SIZE 256
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
#define STM_CONFIG_SMI_UNBLOCKING_BY_VMX_OFF 0x1
|
||||
|
||||
//
|
||||
// TXT debug
|
||||
//
|
||||
#define SW_SMI_STM_ADD_RUNTIME_RESOURCES_SUB_FUNC 0
|
||||
#define SW_SMI_STM_READ_BIOS_RESOURCES_SUB_FUNC 1
|
||||
#define SW_SMI_STM_REPLACE_BIOS_RESOURCES_SUB_FUNC 2
|
||||
|
||||
typedef struct {
|
||||
UINT32 BufferSize;
|
||||
UINT32 Reserved;
|
||||
//UINT8 Data[];
|
||||
} TXT_BIOS_DEBUG;
|
||||
|
||||
#pragma pack (pop)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,676 @@
|
|||
/** @file
|
||||
The CPU specific programming for PiSmmCpuDxeSmm module.
|
||||
|
||||
Copyright (c) 2010 - 2016, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include <PiSmm.h>
|
||||
#include <Library/SmmCpuFeaturesLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/MtrrLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Register/Cpuid.h>
|
||||
#include <Register/SmramSaveStateMap.h>
|
||||
|
||||
//
|
||||
// Machine Specific Registers (MSRs)
|
||||
//
|
||||
#define SMM_FEATURES_LIB_IA32_MTRR_CAP 0x0FE
|
||||
#define SMM_FEATURES_LIB_IA32_FEATURE_CONTROL 0x03A
|
||||
#define SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE 0x1F2
|
||||
#define SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK 0x1F3
|
||||
#define SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE 0x0A0
|
||||
#define SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSMASK 0x0A1
|
||||
#define EFI_MSR_SMRR_MASK 0xFFFFF000
|
||||
#define EFI_MSR_SMRR_PHYS_MASK_VALID BIT11
|
||||
#define SMM_FEATURES_LIB_SMM_FEATURE_CONTROL 0x4E0
|
||||
|
||||
//
|
||||
// MSRs required for configuration of SMM Code Access Check
|
||||
//
|
||||
#define SMM_FEATURES_LIB_IA32_MCA_CAP 0x17D
|
||||
#define SMM_CODE_ACCESS_CHK_BIT BIT58
|
||||
|
||||
//
|
||||
// Set default value to assume SMRR is not supported
|
||||
//
|
||||
BOOLEAN mSmrrSupported = FALSE;
|
||||
|
||||
//
|
||||
// Set default value to assume MSR_SMM_FEATURE_CONTROL is not supported
|
||||
//
|
||||
BOOLEAN mSmmFeatureControlSupported = FALSE;
|
||||
|
||||
//
|
||||
// Set default value to assume IA-32 Architectural MSRs are used
|
||||
//
|
||||
UINT32 mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE;
|
||||
UINT32 mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK;
|
||||
|
||||
//
|
||||
// Set default value to assume MTRRs need to be configured on each SMI
|
||||
//
|
||||
BOOLEAN mNeedConfigureMtrrs = TRUE;
|
||||
|
||||
//
|
||||
// Array for state of SMRR enable on all CPUs
|
||||
//
|
||||
BOOLEAN *mSmrrEnabled;
|
||||
|
||||
/**
|
||||
The constructor function
|
||||
|
||||
@param[in] ImageHandle The firmware allocated handle for the EFI image.
|
||||
@param[in] SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmCpuFeaturesLibConstructor (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
UINT32 RegEax;
|
||||
UINT32 RegEdx;
|
||||
UINTN FamilyId;
|
||||
UINTN ModelId;
|
||||
|
||||
//
|
||||
// Retrieve CPU Family and Model
|
||||
//
|
||||
AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, &RegEdx);
|
||||
FamilyId = (RegEax >> 8) & 0xf;
|
||||
ModelId = (RegEax >> 4) & 0xf;
|
||||
if (FamilyId == 0x06 || FamilyId == 0x0f) {
|
||||
ModelId = ModelId | ((RegEax >> 12) & 0xf0);
|
||||
}
|
||||
|
||||
//
|
||||
// Check CPUID(CPUID_VERSION_INFO).EDX[12] for MTRR capability
|
||||
//
|
||||
if ((RegEdx & BIT12) != 0) {
|
||||
//
|
||||
// Check MTRR_CAP MSR bit 11 for SMRR support
|
||||
//
|
||||
if ((AsmReadMsr64 (SMM_FEATURES_LIB_IA32_MTRR_CAP) & BIT11) != 0) {
|
||||
mSmrrSupported = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Intel(R) 64 and IA-32 Architectures Software Developer's Manual
|
||||
// Volume 3C, Section 35.3 MSRs in the Intel(R) Atom(TM) Processor Family
|
||||
//
|
||||
// If CPU Family/Model is 06_1CH, 06_26H, 06_27H, 06_35H or 06_36H, then
|
||||
// SMRR Physical Base and SMM Physical Mask MSRs are not available.
|
||||
//
|
||||
if (FamilyId == 0x06) {
|
||||
if (ModelId == 0x1C || ModelId == 0x26 || ModelId == 0x27 || ModelId == 0x35 || ModelId == 0x36) {
|
||||
mSmrrSupported = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Intel(R) 64 and IA-32 Architectures Software Developer's Manual
|
||||
// Volume 3C, Section 35.2 MSRs in the Intel(R) Core(TM) 2 Processor Family
|
||||
//
|
||||
// If CPU Family/Model is 06_0F or 06_17, then use Intel(R) Core(TM) 2
|
||||
// Processor Family MSRs
|
||||
//
|
||||
if (FamilyId == 0x06) {
|
||||
if (ModelId == 0x17 || ModelId == 0x0f) {
|
||||
mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE;
|
||||
mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSMASK;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Intel(R) 64 and IA-32 Architectures Software Developer's Manual
|
||||
// Volume 3C, Section 34.4.2 SMRAM Caching
|
||||
// An IA-32 processor does not automatically write back and invalidate its
|
||||
// caches before entering SMM or before exiting SMM. Because of this behavior,
|
||||
// care must be taken in the placement of the SMRAM in system memory and in
|
||||
// the caching of the SMRAM to prevent cache incoherence when switching back
|
||||
// and forth between SMM and protected mode operation.
|
||||
//
|
||||
// An IA-32 processor is a processor that does not support the Intel 64
|
||||
// Architecture. Support for the Intel 64 Architecture can be detected from
|
||||
// CPUID(CPUID_EXTENDED_CPU_SIG).EDX[29]
|
||||
//
|
||||
// If an IA-32 processor is detected, then set mNeedConfigureMtrrs to TRUE,
|
||||
// so caches are flushed on SMI entry and SMI exit, the interrupted code
|
||||
// MTRRs are saved/restored, and MTRRs for SMM are loaded.
|
||||
//
|
||||
AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
|
||||
if (RegEax >= CPUID_EXTENDED_CPU_SIG) {
|
||||
AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
|
||||
if ((RegEdx & BIT29) != 0) {
|
||||
mNeedConfigureMtrrs = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate array for state of SMRR enable on all CPUs
|
||||
//
|
||||
mSmrrEnabled = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
|
||||
ASSERT (mSmrrEnabled != NULL);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Called during the very first SMI into System Management Mode to initialize
|
||||
CPU features, including SMBASE, for the currently executing CPU. Since this
|
||||
is the first SMI, the SMRAM Save State Map is at the default address of
|
||||
SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET. The currently executing
|
||||
CPU is specified by CpuIndex and CpuIndex can be used to access information
|
||||
about the currently executing CPU in the ProcessorInfo array and the
|
||||
HotPlugCpuData data structure.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to initialize. The value
|
||||
must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] IsMonarch TRUE if the CpuIndex is the index of the CPU that
|
||||
was elected as monarch during System Management
|
||||
Mode initialization.
|
||||
FALSE if the CpuIndex is not the index of the CPU
|
||||
that was elected as monarch during System
|
||||
Management Mode initialization.
|
||||
@param[in] ProcessorInfo Pointer to an array of EFI_PROCESSOR_INFORMATION
|
||||
structures. ProcessorInfo[CpuIndex] contains the
|
||||
information for the currently executing CPU.
|
||||
@param[in] CpuHotPlugData Pointer to the CPU_HOT_PLUG_DATA structure that
|
||||
contains the ApidId and SmBase arrays.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesInitializeProcessor (
|
||||
IN UINTN CpuIndex,
|
||||
IN BOOLEAN IsMonarch,
|
||||
IN EFI_PROCESSOR_INFORMATION *ProcessorInfo,
|
||||
IN CPU_HOT_PLUG_DATA *CpuHotPlugData
|
||||
)
|
||||
{
|
||||
SMRAM_SAVE_STATE_MAP *CpuState;
|
||||
UINT64 FeatureControl;
|
||||
UINT32 RegEax;
|
||||
UINT32 RegEdx;
|
||||
UINTN FamilyId;
|
||||
UINTN ModelId;
|
||||
|
||||
//
|
||||
// Configure SMBASE.
|
||||
//
|
||||
CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
|
||||
CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
|
||||
|
||||
//
|
||||
// Intel(R) 64 and IA-32 Architectures Software Developer's Manual
|
||||
// Volume 3C, Section 35.2 MSRs in the Intel(R) Core(TM) 2 Processor Family
|
||||
//
|
||||
// If Intel(R) Core(TM) Core(TM) 2 Processor Family MSRs are being used, then
|
||||
// make sure SMRR Enable(BIT3) of MSR_FEATURE_CONTROL MSR(0x3A) is set before
|
||||
// accessing SMRR base/mask MSRs. If Lock(BIT0) of MSR_FEATURE_CONTROL MSR(0x3A)
|
||||
// is set, then the MSR is locked and can not be modified.
|
||||
//
|
||||
if (mSmrrSupported && mSmrrPhysBaseMsr == SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE) {
|
||||
FeatureControl = AsmReadMsr64 (SMM_FEATURES_LIB_IA32_FEATURE_CONTROL);
|
||||
if ((FeatureControl & BIT3) == 0) {
|
||||
if ((FeatureControl & BIT0) == 0) {
|
||||
AsmWriteMsr64 (SMM_FEATURES_LIB_IA32_FEATURE_CONTROL, FeatureControl | BIT3);
|
||||
} else {
|
||||
mSmrrSupported = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If SMRR is supported, then program SMRR base/mask MSRs.
|
||||
// The EFI_MSR_SMRR_PHYS_MASK_VALID bit is not set until the first normal SMI.
|
||||
// The code that initializes SMM environment is running in normal mode
|
||||
// from SMRAM region. If SMRR is enabled here, then the SMRAM region
|
||||
// is protected and the normal mode code execution will fail.
|
||||
//
|
||||
if (mSmrrSupported) {
|
||||
AsmWriteMsr64 (mSmrrPhysBaseMsr, CpuHotPlugData->SmrrBase | MTRR_CACHE_WRITE_BACK);
|
||||
AsmWriteMsr64 (mSmrrPhysMaskMsr, (~(CpuHotPlugData->SmrrSize - 1) & EFI_MSR_SMRR_MASK));
|
||||
mSmrrEnabled[CpuIndex] = FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve CPU Family and Model
|
||||
//
|
||||
AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, &RegEdx);
|
||||
FamilyId = (RegEax >> 8) & 0xf;
|
||||
ModelId = (RegEax >> 4) & 0xf;
|
||||
if (FamilyId == 0x06 || FamilyId == 0x0f) {
|
||||
ModelId = ModelId | ((RegEax >> 12) & 0xf0);
|
||||
}
|
||||
|
||||
//
|
||||
// Intel(R) 64 and IA-32 Architectures Software Developer's Manual
|
||||
// Volume 3C, Section 35.10.1 MSRs in 4th Generation Intel(R) Core(TM)
|
||||
// Processor Family.
|
||||
//
|
||||
// If CPU Family/Model is 06_3C, 06_45, or 06_46 then use 4th Generation
|
||||
// Intel(R) Core(TM) Processor Family MSRs.
|
||||
//
|
||||
if (FamilyId == 0x06) {
|
||||
if (ModelId == 0x3C || ModelId == 0x45 || ModelId == 0x46) {
|
||||
//
|
||||
// Check to see if the CPU supports the SMM Code Access Check feature
|
||||
// Do not access this MSR unless the CPU supports the SmmRegFeatureControl
|
||||
//
|
||||
if ((AsmReadMsr64 (SMM_FEATURES_LIB_IA32_MCA_CAP) & SMM_CODE_ACCESS_CHK_BIT) != 0) {
|
||||
mSmmFeatureControlSupported = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This function updates the SMRAM save state on the currently executing CPU
|
||||
to resume execution at a specific address after an RSM instruction. This
|
||||
function must evaluate the SMRAM save state to determine the execution mode
|
||||
the RSM instruction resumes and update the resume execution address with
|
||||
either NewInstructionPointer32 or NewInstructionPoint. The auto HALT restart
|
||||
flag in the SMRAM save state must always be cleared. This function returns
|
||||
the value of the instruction pointer from the SMRAM save state that was
|
||||
replaced. If this function returns 0, then the SMRAM save state was not
|
||||
modified.
|
||||
|
||||
This function is called during the very first SMI on each CPU after
|
||||
SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
|
||||
to signal that the SMBASE of each CPU has been updated before the default
|
||||
SMBASE address is used for the first SMI to the next CPU.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to hook. The value
|
||||
must be between 0 and the NumberOfCpus
|
||||
field in the System Management System Table
|
||||
(SMST).
|
||||
@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 execution mode from 64-bit SMM.
|
||||
@param[in] NewInstructionPointer Instruction pointer to use if resuming to
|
||||
same execution mode as SMM.
|
||||
|
||||
@retval 0 This function did modify the SMRAM save state.
|
||||
@retval > 0 The original instruction pointer value from the SMRAM save state
|
||||
before it was replaced.
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
SmmCpuFeaturesHookReturnFromSmm (
|
||||
IN UINTN CpuIndex,
|
||||
IN SMRAM_SAVE_STATE_MAP *CpuState,
|
||||
IN UINT64 NewInstructionPointer32,
|
||||
IN UINT64 NewInstructionPointer
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Hook point in normal execution mode that allows the one CPU that was elected
|
||||
as monarch during System Management Mode initialization to perform additional
|
||||
initialization actions immediately after all of the CPUs have processed their
|
||||
first SMI and called SmmCpuFeaturesInitializeProcessor() relocating SMBASE
|
||||
into a buffer in SMRAM and called SmmCpuFeaturesHookReturnFromSmm().
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesSmmRelocationComplete (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Return the size, in bytes, of a custom SMI Handler in bytes. If 0 is
|
||||
returned, then a custom SMI handler is not provided by this library,
|
||||
and the default SMI handler must be used.
|
||||
|
||||
@retval 0 Use the default SMI handler.
|
||||
@retval > 0 Use the SMI handler installed by SmmCpuFeaturesInstallSmiHandler()
|
||||
The caller is required to allocate enough SMRAM for each CPU to
|
||||
support the size of the custom SMI handler.
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
SmmCpuFeaturesGetSmiHandlerSize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Return the offset to SMBASE, of a custom native SMI Handler in bytes.
|
||||
If 0 is returned, then a custom SMI handler is not provided by this library,
|
||||
and the default SMI handler must be used.
|
||||
|
||||
@retval 0 Use the default SMI handler.
|
||||
@retval > 0 If STM is enabled, TXT_PROCESSOR_SMM_DESCRIPTOR.SmmSmiHandlerRip
|
||||
is SmiHandlerOffset + SMBASE.
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
SmmCpuFeaturesGetSmiHandlerOffset (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Install a custom SMI handler for the CPU specified by CpuIndex. This function
|
||||
is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size is greater
|
||||
than zero and 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
|
||||
SmmCpuFeaturesInstallSmiHandler (
|
||||
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
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Determines if MTRR registers must be configured to set SMRAM cache-ability
|
||||
when executing in System Management Mode.
|
||||
|
||||
@retval TRUE MTRR registers must be configured to set SMRAM cache-ability.
|
||||
@retval FALSE MTRR registers do not need to be configured to set SMRAM
|
||||
cache-ability.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
SmmCpuFeaturesNeedConfigureMtrrs (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return mNeedConfigureMtrrs;
|
||||
}
|
||||
|
||||
/**
|
||||
Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
|
||||
returns TRUE.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesDisableSmrr (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (mSmrrSupported && mNeedConfigureMtrrs) {
|
||||
AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64(mSmrrPhysMaskMsr) & ~EFI_MSR_SMRR_PHYS_MASK_VALID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Enable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
|
||||
returns TRUE.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesReenableSmrr (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (mSmrrSupported && mNeedConfigureMtrrs) {
|
||||
AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64(mSmrrPhysMaskMsr) | EFI_MSR_SMRR_PHYS_MASK_VALID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Processor specific hook point each time a CPU enters System Management Mode.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU that has entered SMM. The value
|
||||
must be between 0 and the NumberOfCpus field in the
|
||||
System Management System Table (SMST).
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesRendezvousEntry (
|
||||
IN UINTN CpuIndex
|
||||
)
|
||||
{
|
||||
//
|
||||
// If SMRR is supported and this is the first normal SMI, then enable SMRR
|
||||
//
|
||||
if (mSmrrSupported && !mSmrrEnabled[CpuIndex]) {
|
||||
AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64 (mSmrrPhysMaskMsr) | EFI_MSR_SMRR_PHYS_MASK_VALID);
|
||||
mSmrrEnabled[CpuIndex] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Processor specific hook point each time a CPU exits System Management Mode.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU that is exiting SMM. The value must
|
||||
be between 0 and the NumberOfCpus field in the System
|
||||
Management System Table (SMST).
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesRendezvousExit (
|
||||
IN UINTN CpuIndex
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Check to see if an SMM register is supported by a specified CPU.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to check for SMM register support.
|
||||
The value must be between 0 and the NumberOfCpus field
|
||||
in the System Management System Table (SMST).
|
||||
@param[in] RegName Identifies the SMM register to check for support.
|
||||
|
||||
@retval TRUE The SMM register specified by RegName is supported by the CPU
|
||||
specified by CpuIndex.
|
||||
@retval FALSE The SMM register specified by RegName is not supported by the
|
||||
CPU specified by CpuIndex.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
SmmCpuFeaturesIsSmmRegisterSupported (
|
||||
IN UINTN CpuIndex,
|
||||
IN SMM_REG_NAME RegName
|
||||
)
|
||||
{
|
||||
if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the current value of the SMM register for the specified CPU.
|
||||
If the SMM register is not supported, then 0 is returned.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to read the SMM register. The
|
||||
value must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] RegName Identifies the SMM register to read.
|
||||
|
||||
@return The value of the SMM register specified by RegName from the CPU
|
||||
specified by CpuIndex.
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
SmmCpuFeaturesGetSmmRegister (
|
||||
IN UINTN CpuIndex,
|
||||
IN SMM_REG_NAME RegName
|
||||
)
|
||||
{
|
||||
if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
|
||||
return AsmReadMsr64 (SMM_FEATURES_LIB_SMM_FEATURE_CONTROL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the value of an SMM register on a specified CPU.
|
||||
If the SMM register is not supported, then no action is performed.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to write the SMM register. The
|
||||
value must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] RegName Identifies the SMM register to write.
|
||||
registers are read-only.
|
||||
@param[in] Value The value to write to the SMM register.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesSetSmmRegister (
|
||||
IN UINTN CpuIndex,
|
||||
IN SMM_REG_NAME RegName,
|
||||
IN UINT64 Value
|
||||
)
|
||||
{
|
||||
if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
|
||||
AsmWriteMsr64 (SMM_FEATURES_LIB_SMM_FEATURE_CONTROL, Value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Read an SMM Save State register on the target processor. If this function
|
||||
returns EFI_UNSUPPORTED, then the caller is responsible for reading the
|
||||
SMM Save Sate register.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to read the SMM Save State. The
|
||||
value must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] Register The SMM Save State register to read.
|
||||
@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_INVALID_PARAMTER Buffer is NULL.
|
||||
@retval EFI_UNSUPPORTED This function does not support reading Register.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmCpuFeaturesReadSaveStateRegister (
|
||||
IN UINTN CpuIndex,
|
||||
IN EFI_SMM_SAVE_STATE_REGISTER Register,
|
||||
IN UINTN Width,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Writes an SMM Save State register on the target processor. If this function
|
||||
returns EFI_UNSUPPORTED, then the caller is responsible for writing the
|
||||
SMM Save Sate register.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to write the SMM Save State. The
|
||||
value must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] Register The SMM Save State register to write.
|
||||
@param[in] Width The number of bytes to write to 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_INVALID_PARAMTER Buffer is NULL.
|
||||
@retval EFI_UNSUPPORTED This function does not support writing Register.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmCpuFeaturesWriteSaveStateRegister (
|
||||
IN UINTN CpuIndex,
|
||||
IN EFI_SMM_SAVE_STATE_REGISTER Register,
|
||||
IN UINTN Width,
|
||||
IN CONST VOID *Buffer
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
This function is hook point called after the gEfiSmmReadyToLockProtocolGuid
|
||||
notification is completely processed.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesCompleteSmmReadyToLock (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
This API provides a method for a CPU to allocate a specific region for storing page tables.
|
||||
|
||||
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.
|
||||
|
||||
This function can also return NULL if there is no preference on where the page tables are allocated in SMRAM.
|
||||
|
||||
@param Pages The number of 4 KB pages to allocate.
|
||||
|
||||
@return A pointer to the allocated buffer for page tables.
|
||||
@retval NULL Fail to allocate a specific region for storing page tables,
|
||||
Or there is no preference on where the page tables are allocated in SMRAM.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
EFIAPI
|
||||
SmmCpuFeaturesAllocatePageTableMemory (
|
||||
IN UINTN Pages
|
||||
)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
## @file
|
||||
# The CPU specific programming for PiSmmCpuDxeSmm module.
|
||||
#
|
||||
# Copyright (c) 2009 - 2016, Intel Corporation. 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = SmmCpuFeaturesLib
|
||||
MODULE_UNI_FILE = SmmCpuFeaturesLib.uni
|
||||
FILE_GUID = FC3DC10D-D271-422a-AFF3-CBCF70344431
|
||||
MODULE_TYPE = DXE_SMM_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = SmmCpuFeaturesLib
|
||||
CONSTRUCTOR = SmmCpuFeaturesLibConstructor
|
||||
|
||||
[Sources]
|
||||
SmmCpuFeaturesLib.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
StmCpuPkg/StmCpuPkg.dec
|
||||
UefiCpuPkg/UefiCpuPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
PcdLib
|
||||
MemoryAllocationLib
|
||||
DebugLib
|
||||
|
||||
[Pcd]
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## SOMETIMES_CONSUMES
|
|
@ -0,0 +1,18 @@
|
|||
// /** @file
|
||||
// The CPU specific programming for PiSmmCpuDxeSmm module.
|
||||
//
|
||||
// Copyright (c) 2009 - 2015, Intel Corporation. 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "The CPU specific programming for PiSmmCpuDxeSmm module."
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "The CPU specific programming for PiSmmCpuDxeSmm module."
|
|
@ -0,0 +1,108 @@
|
|||
/** @file
|
||||
SMM CPU Platform Hook NULL library instance.
|
||||
|
||||
Copyright (c) 2006 - 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
#include <PiSmm.h>
|
||||
#include <Library/SmmCpuPlatformHookLib.h>
|
||||
|
||||
/**
|
||||
Checks if platform produces a valid SMI.
|
||||
|
||||
This function checks if platform produces a valid SMI. This function is
|
||||
called at SMM entry to detect if this is a spurious SMI. This function
|
||||
must be implemented in an MP safe way because it is called by multiple CPU
|
||||
threads.
|
||||
|
||||
@retval TRUE There is a valid SMI
|
||||
@retval FALSE There is no valid SMI
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
PlatformValidSmi (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Clears platform top level SMI status bit.
|
||||
|
||||
This function clears platform top level SMI status bit.
|
||||
|
||||
@retval TRUE The platform top level SMI status is cleared.
|
||||
@retval FALSE The platform top level SMI status cannot be cleared.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ClearTopLevelSmiStatus (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Performs platform specific way of SMM BSP election.
|
||||
|
||||
This function performs platform specific way of SMM BSP election.
|
||||
|
||||
@param IsBsp Output parameter. TRUE: the CPU this function executes
|
||||
on is elected to be the SMM BSP. FALSE: the CPU this
|
||||
function executes on is to be SMM AP.
|
||||
|
||||
@retval EFI_SUCCESS The function executes successfully.
|
||||
@retval EFI_NOT_READY The function does not determine whether this CPU should be
|
||||
BSP or AP. This may occur if hardware init sequence to
|
||||
enable the determination is yet to be done, or the function
|
||||
chooses not to do BSP election and will let SMM CPU driver to
|
||||
use its default BSP election process.
|
||||
@retval EFI_DEVICE_ERROR The function cannot determine whether this CPU should be
|
||||
BSP or AP due to hardware error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PlatformSmmBspElection (
|
||||
OUT BOOLEAN *IsBsp
|
||||
)
|
||||
{
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
Get platform page table attribute.
|
||||
|
||||
This function gets page table attribute of platform.
|
||||
|
||||
@param Address Input parameter. Obtain the page table entries attribute on this address.
|
||||
@param PageSize Output parameter. The size of the page.
|
||||
@param NumOfPages Output parameter. Number of page.
|
||||
@param PageAttribute Output parameter. Paging Attributes (WB, UC, etc).
|
||||
|
||||
@retval EFI_SUCCESS The platform page table attribute from the address is determined.
|
||||
@retval EFI_UNSUPPORTED The platform does not support getting page table attribute for the address.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetPlatformPageTableAttribute (
|
||||
IN UINT64 Address,
|
||||
IN OUT SMM_PAGE_SIZE_TYPE *PageSize,
|
||||
IN OUT UINTN *NumOfPages,
|
||||
IN OUT UINTN *PageAttribute
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
## @file
|
||||
# SMM CPU Platform Hook NULL library instance.
|
||||
#
|
||||
# Copyright (c) 2006 - 2016, Intel Corporation. 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.
|
||||
#
|
||||
##
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Defines Section - statements that will be processed to create a Makefile.
|
||||
#
|
||||
################################################################################
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = SmmCpuPlatformHookLibNull
|
||||
MODULE_UNI_FILE = SmmCpuPlatformHookLibNull.uni
|
||||
FILE_GUID = D6494E1B-E06F-4ab5-B64D-48B25AA9EB33
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = SmmCpuPlatformHookLib
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
SmmCpuPlatformHookLibNull.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
StmCpuPkg/StmCpuPkg.dec
|
||||
UefiCpuPkg/UefiCpuPkg.dec
|
|
@ -0,0 +1,18 @@
|
|||
// /** @file
|
||||
// SMM CPU Platform Hook NULL library instance.
|
||||
//
|
||||
// Copyright (c) 2006 - 2015, Intel Corporation. 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "SMM CPU Platform Hook NULL library instance"
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "SMM CPU Platform Hook NULL library instance."
|
|
@ -0,0 +1,491 @@
|
|||
/** @file
|
||||
Code for Processor S3 restoration
|
||||
|
||||
Copyright (c) 2006 - 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "PiSmmCpuDxeSmm.h"
|
||||
|
||||
typedef struct {
|
||||
UINTN Lock;
|
||||
VOID *StackStart;
|
||||
UINTN StackSize;
|
||||
VOID *ApFunction;
|
||||
IA32_DESCRIPTOR GdtrProfile;
|
||||
IA32_DESCRIPTOR IdtrProfile;
|
||||
UINT32 BufferStart;
|
||||
UINT32 Cr3;
|
||||
} MP_CPU_EXCHANGE_INFO;
|
||||
|
||||
typedef struct {
|
||||
UINT8 *RendezvousFunnelAddress;
|
||||
UINTN PModeEntryOffset;
|
||||
UINTN FlatJumpOffset;
|
||||
UINTN Size;
|
||||
UINTN LModeEntryOffset;
|
||||
UINTN LongJumpOffset;
|
||||
} MP_ASSEMBLY_ADDRESS_MAP;
|
||||
|
||||
/**
|
||||
Get starting address and size of the rendezvous entry for APs.
|
||||
Information for fixing a jump instruction in the code is also returned.
|
||||
|
||||
@param AddressMap Output buffer for address map information.
|
||||
**/
|
||||
VOID *
|
||||
EFIAPI
|
||||
AsmGetAddressMap (
|
||||
MP_ASSEMBLY_ADDRESS_MAP *AddressMap
|
||||
);
|
||||
|
||||
#define LEGACY_REGION_SIZE (2 * 0x1000)
|
||||
#define LEGACY_REGION_BASE (0xA0000 - LEGACY_REGION_SIZE)
|
||||
#define MSR_SPIN_LOCK_INIT_NUM 15
|
||||
|
||||
ACPI_CPU_DATA mAcpiCpuData;
|
||||
UINT32 mNumberToFinish;
|
||||
MP_CPU_EXCHANGE_INFO *mExchangeInfo;
|
||||
BOOLEAN mRestoreSmmConfigurationInS3 = FALSE;
|
||||
VOID *mGdtForAp = NULL;
|
||||
VOID *mIdtForAp = NULL;
|
||||
VOID *mMachineCheckHandlerForAp = NULL;
|
||||
MP_MSR_LOCK *mMsrSpinLocks = NULL;
|
||||
UINTN mMsrSpinLockCount = MSR_SPIN_LOCK_INIT_NUM;
|
||||
UINTN mMsrCount = 0;
|
||||
|
||||
/**
|
||||
Get MSR spin lock by MSR index.
|
||||
|
||||
@param MsrIndex MSR index value.
|
||||
|
||||
@return Pointer to MSR spin lock.
|
||||
|
||||
**/
|
||||
SPIN_LOCK *
|
||||
GetMsrSpinLockByIndex (
|
||||
IN UINT32 MsrIndex
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
for (Index = 0; Index < mMsrCount; Index++) {
|
||||
if (MsrIndex == mMsrSpinLocks[Index].MsrIndex) {
|
||||
return &mMsrSpinLocks[Index].SpinLock;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize MSR spin lock by MSR index.
|
||||
|
||||
@param MsrIndex MSR index value.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitMsrSpinLockByIndex (
|
||||
IN UINT32 MsrIndex
|
||||
)
|
||||
{
|
||||
UINTN NewMsrSpinLockCount;
|
||||
|
||||
if (mMsrSpinLocks == NULL) {
|
||||
mMsrSpinLocks = (MP_MSR_LOCK *) AllocatePool (sizeof (MP_MSR_LOCK) * mMsrSpinLockCount);
|
||||
ASSERT (mMsrSpinLocks != NULL);
|
||||
}
|
||||
if (GetMsrSpinLockByIndex (MsrIndex) == NULL) {
|
||||
//
|
||||
// Initialize spin lock for MSR programming
|
||||
//
|
||||
mMsrSpinLocks[mMsrCount].MsrIndex = MsrIndex;
|
||||
InitializeSpinLock (&mMsrSpinLocks[mMsrCount].SpinLock);
|
||||
mMsrCount ++;
|
||||
if (mMsrCount == mMsrSpinLockCount) {
|
||||
//
|
||||
// If MSR spin lock buffer is full, enlarge it
|
||||
//
|
||||
NewMsrSpinLockCount = mMsrSpinLockCount + MSR_SPIN_LOCK_INIT_NUM;
|
||||
mMsrSpinLocks = ReallocatePool (
|
||||
sizeof (MP_MSR_LOCK) * mMsrSpinLockCount,
|
||||
sizeof (MP_MSR_LOCK) * NewMsrSpinLockCount,
|
||||
mMsrSpinLocks
|
||||
);
|
||||
mMsrSpinLockCount = NewMsrSpinLockCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Sync up the MTRR values for all processors.
|
||||
|
||||
@param MtrrTable Table holding fixed/variable MTRR values to be loaded.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
LoadMtrrData (
|
||||
EFI_PHYSICAL_ADDRESS MtrrTable
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Sync up the MTRR values for all processors.
|
||||
|
||||
Arguments:
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
MTRR_SETTINGS *MtrrSettings;
|
||||
|
||||
MtrrSettings = (MTRR_SETTINGS *) (UINTN) MtrrTable;
|
||||
MtrrSetAllMtrrs (MtrrSettings);
|
||||
}
|
||||
|
||||
/**
|
||||
Programs registers for the calling processor.
|
||||
|
||||
This function programs registers for the calling processor.
|
||||
|
||||
@param RegisterTable Pointer to register table of the running processor.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetProcessorRegister (
|
||||
IN CPU_REGISTER_TABLE *RegisterTable
|
||||
)
|
||||
{
|
||||
CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
|
||||
UINTN Index;
|
||||
UINTN Value;
|
||||
SPIN_LOCK *MsrSpinLock;
|
||||
|
||||
//
|
||||
// Traverse Register Table of this logical processor
|
||||
//
|
||||
RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;
|
||||
for (Index = 0; Index < RegisterTable->TableLength; Index++, RegisterTableEntry++) {
|
||||
//
|
||||
// Check the type of specified register
|
||||
//
|
||||
switch (RegisterTableEntry->RegisterType) {
|
||||
//
|
||||
// The specified register is Control Register
|
||||
//
|
||||
case ControlRegister:
|
||||
switch (RegisterTableEntry->Index) {
|
||||
case 0:
|
||||
Value = AsmReadCr0 ();
|
||||
Value = (UINTN) BitFieldWrite64 (
|
||||
Value,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
|
||||
(UINTN) RegisterTableEntry->Value
|
||||
);
|
||||
AsmWriteCr0 (Value);
|
||||
break;
|
||||
case 2:
|
||||
Value = AsmReadCr2 ();
|
||||
Value = (UINTN) BitFieldWrite64 (
|
||||
Value,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
|
||||
(UINTN) RegisterTableEntry->Value
|
||||
);
|
||||
AsmWriteCr2 (Value);
|
||||
break;
|
||||
case 3:
|
||||
Value = AsmReadCr3 ();
|
||||
Value = (UINTN) BitFieldWrite64 (
|
||||
Value,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
|
||||
(UINTN) RegisterTableEntry->Value
|
||||
);
|
||||
AsmWriteCr3 (Value);
|
||||
break;
|
||||
case 4:
|
||||
Value = AsmReadCr4 ();
|
||||
Value = (UINTN) BitFieldWrite64 (
|
||||
Value,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
|
||||
(UINTN) RegisterTableEntry->Value
|
||||
);
|
||||
AsmWriteCr4 (Value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
//
|
||||
// The specified register is Model Specific Register
|
||||
//
|
||||
case Msr:
|
||||
//
|
||||
// If this function is called to restore register setting after INIT signal,
|
||||
// there is no need to restore MSRs in register table.
|
||||
//
|
||||
if (RegisterTableEntry->ValidBitLength >= 64) {
|
||||
//
|
||||
// If length is not less than 64 bits, then directly write without reading
|
||||
//
|
||||
AsmWriteMsr64 (
|
||||
RegisterTableEntry->Index,
|
||||
RegisterTableEntry->Value
|
||||
);
|
||||
} else {
|
||||
//
|
||||
// Get lock to avoid Package/Core scope MSRs programming issue in parallel execution mode
|
||||
// to make sure MSR read/write operation is atomic.
|
||||
//
|
||||
MsrSpinLock = GetMsrSpinLockByIndex (RegisterTableEntry->Index);
|
||||
AcquireSpinLock (MsrSpinLock);
|
||||
//
|
||||
// Set the bit section according to bit start and length
|
||||
//
|
||||
AsmMsrBitFieldWrite64 (
|
||||
RegisterTableEntry->Index,
|
||||
RegisterTableEntry->ValidBitStart,
|
||||
RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
|
||||
RegisterTableEntry->Value
|
||||
);
|
||||
ReleaseSpinLock (MsrSpinLock);
|
||||
}
|
||||
break;
|
||||
//
|
||||
// Enable or disable cache
|
||||
//
|
||||
case CacheControl:
|
||||
//
|
||||
// If value of the entry is 0, then disable cache. Otherwise, enable cache.
|
||||
//
|
||||
if (RegisterTableEntry->Value == 0) {
|
||||
AsmDisableCache ();
|
||||
} else {
|
||||
AsmEnableCache ();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
AP initialization before SMBASE relocation in the S3 boot path.
|
||||
**/
|
||||
VOID
|
||||
EarlyMPRendezvousProcedure (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
CPU_REGISTER_TABLE *RegisterTableList;
|
||||
UINT32 InitApicId;
|
||||
UINTN Index;
|
||||
|
||||
LoadMtrrData (mAcpiCpuData.MtrrTable);
|
||||
|
||||
//
|
||||
// Find processor number for this CPU.
|
||||
//
|
||||
RegisterTableList = (CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.PreSmmInitRegisterTable;
|
||||
InitApicId = GetInitialApicId ();
|
||||
for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) {
|
||||
if (RegisterTableList[Index].InitialApicId == InitApicId) {
|
||||
SetProcessorRegister (&RegisterTableList[Index]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Count down the number with lock mechanism.
|
||||
//
|
||||
InterlockedDecrement (&mNumberToFinish);
|
||||
}
|
||||
|
||||
/**
|
||||
AP initialization after SMBASE relocation in the S3 boot path.
|
||||
**/
|
||||
VOID
|
||||
MPRendezvousProcedure (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
CPU_REGISTER_TABLE *RegisterTableList;
|
||||
UINT32 InitApicId;
|
||||
UINTN Index;
|
||||
|
||||
ProgramVirtualWireMode ();
|
||||
DisableLvtInterrupts ();
|
||||
|
||||
RegisterTableList = (CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.RegisterTable;
|
||||
InitApicId = GetInitialApicId ();
|
||||
for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) {
|
||||
if (RegisterTableList[Index].InitialApicId == InitApicId) {
|
||||
SetProcessorRegister (&RegisterTableList[Index]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Count down the number with lock mechanism.
|
||||
//
|
||||
InterlockedDecrement (&mNumberToFinish);
|
||||
}
|
||||
|
||||
/**
|
||||
Prepares startup vector for APs.
|
||||
|
||||
This function prepares startup vector for APs.
|
||||
|
||||
@param WorkingBuffer The address of the work buffer.
|
||||
**/
|
||||
VOID
|
||||
PrepareApStartupVector (
|
||||
EFI_PHYSICAL_ADDRESS WorkingBuffer
|
||||
)
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS StartupVector;
|
||||
MP_ASSEMBLY_ADDRESS_MAP AddressMap;
|
||||
|
||||
//
|
||||
// Get the address map of startup code for AP,
|
||||
// including code size, and offset of long jump instructions to redirect.
|
||||
//
|
||||
ZeroMem (&AddressMap, sizeof (AddressMap));
|
||||
AsmGetAddressMap (&AddressMap);
|
||||
|
||||
StartupVector = WorkingBuffer;
|
||||
|
||||
//
|
||||
// Copy AP startup code to startup vector, and then redirect the long jump
|
||||
// instructions for mode switching.
|
||||
//
|
||||
CopyMem ((VOID *) (UINTN) StartupVector, AddressMap.RendezvousFunnelAddress, AddressMap.Size);
|
||||
*(UINT32 *) (UINTN) (StartupVector + AddressMap.FlatJumpOffset + 3) = (UINT32) (StartupVector + AddressMap.PModeEntryOffset);
|
||||
if (AddressMap.LongJumpOffset != 0) {
|
||||
*(UINT32 *) (UINTN) (StartupVector + AddressMap.LongJumpOffset + 2) = (UINT32) (StartupVector + AddressMap.LModeEntryOffset);
|
||||
}
|
||||
|
||||
//
|
||||
// Get the start address of exchange data between BSP and AP.
|
||||
//
|
||||
mExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN) (StartupVector + AddressMap.Size);
|
||||
ZeroMem ((VOID *) mExchangeInfo, sizeof (MP_CPU_EXCHANGE_INFO));
|
||||
|
||||
CopyMem ((VOID *) (UINTN) &mExchangeInfo->GdtrProfile, (VOID *) (UINTN) mAcpiCpuData.GdtrProfile, sizeof (IA32_DESCRIPTOR));
|
||||
CopyMem ((VOID *) (UINTN) &mExchangeInfo->IdtrProfile, (VOID *) (UINTN) mAcpiCpuData.IdtrProfile, sizeof (IA32_DESCRIPTOR));
|
||||
|
||||
//
|
||||
// Copy AP's GDT, IDT and Machine Check handler from SMRAM to ACPI NVS memory
|
||||
//
|
||||
CopyMem ((VOID *) mExchangeInfo->GdtrProfile.Base, mGdtForAp, mExchangeInfo->GdtrProfile.Limit + 1);
|
||||
CopyMem ((VOID *) mExchangeInfo->IdtrProfile.Base, mIdtForAp, mExchangeInfo->IdtrProfile.Limit + 1);
|
||||
CopyMem ((VOID *)(UINTN) mAcpiCpuData.ApMachineCheckHandlerBase, mMachineCheckHandlerForAp, mAcpiCpuData.ApMachineCheckHandlerSize);
|
||||
|
||||
mExchangeInfo->StackStart = (VOID *) (UINTN) mAcpiCpuData.StackAddress;
|
||||
mExchangeInfo->StackSize = mAcpiCpuData.StackSize;
|
||||
mExchangeInfo->BufferStart = (UINT32) StartupVector;
|
||||
mExchangeInfo->Cr3 = (UINT32) (AsmReadCr3 ());
|
||||
}
|
||||
|
||||
/**
|
||||
The function is invoked before SMBASE relocation in S3 path to restores CPU status.
|
||||
|
||||
The function is invoked before SMBASE relocation in S3 path. It does first time microcode load
|
||||
and restores MTRRs for both BSP and APs.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EarlyInitializeCpu (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
CPU_REGISTER_TABLE *RegisterTableList;
|
||||
UINT32 InitApicId;
|
||||
UINTN Index;
|
||||
|
||||
LoadMtrrData (mAcpiCpuData.MtrrTable);
|
||||
|
||||
//
|
||||
// Find processor number for this CPU.
|
||||
//
|
||||
RegisterTableList = (CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.PreSmmInitRegisterTable;
|
||||
InitApicId = GetInitialApicId ();
|
||||
for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) {
|
||||
if (RegisterTableList[Index].InitialApicId == InitApicId) {
|
||||
SetProcessorRegister (&RegisterTableList[Index]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ProgramVirtualWireMode ();
|
||||
|
||||
PrepareApStartupVector (mAcpiCpuData.StartupVector);
|
||||
|
||||
mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1;
|
||||
mExchangeInfo->ApFunction = (VOID *) (UINTN) EarlyMPRendezvousProcedure;
|
||||
|
||||
//
|
||||
// Send INIT IPI - SIPI to all APs
|
||||
//
|
||||
SendInitSipiSipiAllExcludingSelf ((UINT32)mAcpiCpuData.StartupVector);
|
||||
|
||||
while (mNumberToFinish > 0) {
|
||||
CpuPause ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
The function is invoked after SMBASE relocation in S3 path to restores CPU status.
|
||||
|
||||
The function is invoked after SMBASE relocation in S3 path. It restores configuration according to
|
||||
data saved by normal boot path for both BSP and APs.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitializeCpu (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
CPU_REGISTER_TABLE *RegisterTableList;
|
||||
UINT32 InitApicId;
|
||||
UINTN Index;
|
||||
|
||||
RegisterTableList = (CPU_REGISTER_TABLE *) (UINTN) mAcpiCpuData.RegisterTable;
|
||||
InitApicId = GetInitialApicId ();
|
||||
for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) {
|
||||
if (RegisterTableList[Index].InitialApicId == InitApicId) {
|
||||
SetProcessorRegister (&RegisterTableList[Index]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mNumberToFinish = mAcpiCpuData.NumberOfCpus - 1;
|
||||
//
|
||||
// StackStart was updated when APs were waken up in EarlyInitializeCpu.
|
||||
// Re-initialize StackAddress to original beginning address.
|
||||
//
|
||||
mExchangeInfo->StackStart = (VOID *) (UINTN) mAcpiCpuData.StackAddress;
|
||||
mExchangeInfo->ApFunction = (VOID *) (UINTN) MPRendezvousProcedure;
|
||||
|
||||
//
|
||||
// Send INIT IPI - SIPI to all APs
|
||||
//
|
||||
SendInitSipiSipiAllExcludingSelf ((UINT32)mAcpiCpuData.StartupVector);
|
||||
|
||||
while (mNumberToFinish > 0) {
|
||||
CpuPause ();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,486 @@
|
|||
/** @file
|
||||
Implementation of SMM CPU Services Protocol.
|
||||
|
||||
Copyright (c) 2011 - 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "PiSmmCpuDxeSmm.h"
|
||||
|
||||
//
|
||||
// SMM CPU Service Protocol instance
|
||||
//
|
||||
EFI_SMM_CPU_SERVICE_PROTOCOL mSmmCpuService = {
|
||||
SmmGetProcessorInfo,
|
||||
SmmSwitchBsp,
|
||||
SmmAddProcessor,
|
||||
SmmRemoveProcessor,
|
||||
SmmWhoAmI,
|
||||
SmmRegisterExceptionHandler
|
||||
};
|
||||
|
||||
/**
|
||||
Get Package ID/Core ID/Thread ID of a processor.
|
||||
|
||||
APIC ID must be an initial APIC ID.
|
||||
|
||||
The algorithm below assumes the target system has symmetry across physical package boundaries
|
||||
with respect to the number of logical processors per package, number of cores per package.
|
||||
|
||||
@param ApicId APIC ID of the target logical processor.
|
||||
@param Location Returns the processor location information.
|
||||
**/
|
||||
VOID
|
||||
SmmGetProcessorLocation (
|
||||
IN UINT32 ApicId,
|
||||
OUT EFI_CPU_PHYSICAL_LOCATION *Location
|
||||
)
|
||||
{
|
||||
UINTN ThreadBits;
|
||||
UINTN CoreBits;
|
||||
UINT32 RegEax;
|
||||
UINT32 RegEbx;
|
||||
UINT32 RegEcx;
|
||||
UINT32 RegEdx;
|
||||
UINT32 MaxCpuIdIndex;
|
||||
UINT32 SubIndex;
|
||||
UINTN LevelType;
|
||||
UINT32 MaxLogicProcessorsPerPackage;
|
||||
UINT32 MaxCoresPerPackage;
|
||||
BOOLEAN TopologyLeafSupported;
|
||||
|
||||
ASSERT (Location != NULL);
|
||||
|
||||
ThreadBits = 0;
|
||||
CoreBits = 0;
|
||||
TopologyLeafSupported = FALSE;
|
||||
|
||||
//
|
||||
// Check if the processor is capable of supporting more than one logical processor.
|
||||
//
|
||||
AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);
|
||||
ASSERT ((RegEdx & BIT28) != 0);
|
||||
|
||||
//
|
||||
// Assume three-level mapping of APIC ID: Package:Core:SMT.
|
||||
//
|
||||
|
||||
//
|
||||
// Get the max index of basic CPUID
|
||||
//
|
||||
AsmCpuid (CPUID_SIGNATURE, &MaxCpuIdIndex, NULL, NULL, NULL);
|
||||
|
||||
//
|
||||
// If the extended topology enumeration leaf is available, it
|
||||
// is the preferred mechanism for enumerating topology.
|
||||
//
|
||||
if (MaxCpuIdIndex >= CPUID_EXTENDED_TOPOLOGY) {
|
||||
AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, &RegEax, &RegEbx, &RegEcx, NULL);
|
||||
//
|
||||
// If CPUID.(EAX=0BH, ECX=0H):EBX returns zero and maximum input value for
|
||||
// basic CPUID information is greater than 0BH, then CPUID.0BH leaf is not
|
||||
// supported on that processor.
|
||||
//
|
||||
if ((RegEbx & 0xffff) != 0) {
|
||||
TopologyLeafSupported = TRUE;
|
||||
|
||||
//
|
||||
// Sub-leaf index 0 (ECX= 0 as input) provides enumeration parameters to extract
|
||||
// the SMT sub-field of x2APIC ID.
|
||||
//
|
||||
LevelType = (RegEcx >> 8) & 0xff;
|
||||
ASSERT (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT);
|
||||
if ((RegEbx & 0xffff) > 1 ) {
|
||||
ThreadBits = RegEax & 0x1f;
|
||||
} else {
|
||||
//
|
||||
// HT is not supported
|
||||
//
|
||||
ThreadBits = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Software must not assume any "level type" encoding
|
||||
// value to be related to any sub-leaf index, except sub-leaf 0.
|
||||
//
|
||||
SubIndex = 1;
|
||||
do {
|
||||
AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, SubIndex, &RegEax, NULL, &RegEcx, NULL);
|
||||
LevelType = (RegEcx >> 8) & 0xff;
|
||||
if (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE) {
|
||||
CoreBits = (RegEax & 0x1f) - ThreadBits;
|
||||
break;
|
||||
}
|
||||
SubIndex++;
|
||||
} while (LevelType != CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
if (!TopologyLeafSupported) {
|
||||
AsmCpuid (CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);
|
||||
MaxLogicProcessorsPerPackage = (RegEbx >> 16) & 0xff;
|
||||
if (MaxCpuIdIndex >= CPUID_CACHE_PARAMS) {
|
||||
AsmCpuidEx (CPUID_CACHE_PARAMS, 0, &RegEax, NULL, NULL, NULL);
|
||||
MaxCoresPerPackage = (RegEax >> 26) + 1;
|
||||
} else {
|
||||
//
|
||||
// Must be a single-core processor.
|
||||
//
|
||||
MaxCoresPerPackage = 1;
|
||||
}
|
||||
|
||||
ThreadBits = (UINTN) (HighBitSet32 (MaxLogicProcessorsPerPackage / MaxCoresPerPackage - 1) + 1);
|
||||
CoreBits = (UINTN) (HighBitSet32 (MaxCoresPerPackage - 1) + 1);
|
||||
}
|
||||
|
||||
Location->Thread = ApicId & ~((-1) << ThreadBits);
|
||||
Location->Core = (ApicId >> ThreadBits) & ~((-1) << CoreBits);
|
||||
Location->Package = (ApicId >> (ThreadBits+ CoreBits));
|
||||
}
|
||||
|
||||
/**
|
||||
Gets processor information on the requested processor at the instant this call is made.
|
||||
|
||||
@param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param[in] ProcessorNumber The handle number of processor.
|
||||
@param[out] ProcessorInfoBuffer A pointer to the buffer where information for
|
||||
the requested processor is deposited.
|
||||
|
||||
@retval EFI_SUCCESS Processor information was returned.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
|
||||
@retval EFI_NOT_FOUND The processor with the handle specified by
|
||||
ProcessorNumber does not exist in the platform.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmGetProcessorInfo (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN UINTN ProcessorNumber,
|
||||
OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
|
||||
)
|
||||
{
|
||||
//
|
||||
// Check parameter
|
||||
//
|
||||
if (ProcessorNumber >= mMaxNumberOfCpus || ProcessorInfoBuffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (gSmmCpuPrivate->ProcessorInfo[ProcessorNumber].ProcessorId == INVALID_APIC_ID) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// Fill in processor information
|
||||
//
|
||||
CopyMem (ProcessorInfoBuffer, &gSmmCpuPrivate->ProcessorInfo[ProcessorNumber], sizeof (EFI_PROCESSOR_INFORMATION));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This service switches the requested AP to be the BSP since the next SMI.
|
||||
|
||||
@param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
|
||||
|
||||
@retval EFI_SUCCESS BSP will be switched in next SMI.
|
||||
@retval EFI_UNSUPPORTED Switching the BSP or a processor to be hot-removed is not supported.
|
||||
@retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmSwitchBsp (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN UINTN ProcessorNumber
|
||||
)
|
||||
{
|
||||
//
|
||||
// Check parameter
|
||||
//
|
||||
if (ProcessorNumber >= mMaxNumberOfCpus) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (gSmmCpuPrivate->ProcessorInfo[ProcessorNumber].ProcessorId == INVALID_APIC_ID) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (gSmmCpuPrivate->Operation[ProcessorNumber] != SmmCpuNone ||
|
||||
gSmst->CurrentlyExecutingCpu == ProcessorNumber) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Setting of the BSP for next SMI is pending until all SMI handlers are finished
|
||||
//
|
||||
gSmmCpuPrivate->Operation[ProcessorNumber] = SmmCpuSwitchBsp;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Notify that a processor was hot-added.
|
||||
|
||||
@param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param[in] ProcessorId Local APIC ID of the hot-added processor.
|
||||
@param[out] ProcessorNumber The handle number of the hot-added processor.
|
||||
|
||||
@retval EFI_SUCCESS The hot-addition of the specified processors was successfully notified.
|
||||
@retval EFI_UNSUPPORTED Hot addition of processor is not supported.
|
||||
@retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
|
||||
@retval EFI_ALREADY_STARTED The processor is already online in the system.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmAddProcessor (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN UINT64 ProcessorId,
|
||||
OUT UINTN *ProcessorNumber
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
|
||||
if (!FeaturePcdGet (PcdCpuHotPlugSupport)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Check parameter
|
||||
//
|
||||
if (ProcessorNumber == NULL || ProcessorId == INVALID_APIC_ID) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if the processor already exists
|
||||
//
|
||||
|
||||
for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
|
||||
if (gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == ProcessorId) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check CPU hot plug data. The CPU RAS handler should have created the mapping
|
||||
// of the APIC ID to SMBASE.
|
||||
//
|
||||
for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
|
||||
if (mCpuHotPlugData.ApicId[Index] == ProcessorId &&
|
||||
gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == INVALID_APIC_ID) {
|
||||
gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId = ProcessorId;
|
||||
gSmmCpuPrivate->ProcessorInfo[Index].StatusFlag = 0;
|
||||
SmmGetProcessorLocation ((UINT32)ProcessorId, &gSmmCpuPrivate->ProcessorInfo[Index].Location);
|
||||
|
||||
*ProcessorNumber = Index;
|
||||
gSmmCpuPrivate->Operation[Index] = SmmCpuAdd;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/**
|
||||
Notify that a processor was hot-removed.
|
||||
|
||||
@param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param[in] ProcessorNumber The handle number of the hot-added processor.
|
||||
|
||||
@retval EFI_SUCCESS The hot-removal of the specified processors was successfully notified.
|
||||
@retval EFI_UNSUPPORTED Hot removal of processor is not supported.
|
||||
@retval EFI_UNSUPPORTED Hot removal of BSP is not supported.
|
||||
@retval EFI_UNSUPPORTED Hot removal of a processor with pending hot-plug operation is not supported.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmRemoveProcessor (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN UINTN ProcessorNumber
|
||||
)
|
||||
{
|
||||
if (!FeaturePcdGet (PcdCpuHotPlugSupport)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Check parameter
|
||||
//
|
||||
if (ProcessorNumber >= mMaxNumberOfCpus ||
|
||||
gSmmCpuPrivate->ProcessorInfo[ProcessorNumber].ProcessorId == INVALID_APIC_ID) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Can't remove BSP
|
||||
//
|
||||
if (ProcessorNumber == gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (gSmmCpuPrivate->Operation[ProcessorNumber] != SmmCpuNone) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
gSmmCpuPrivate->ProcessorInfo[ProcessorNumber].ProcessorId = INVALID_APIC_ID;
|
||||
mCpuHotPlugData.ApicId[ProcessorNumber] = INVALID_APIC_ID;
|
||||
|
||||
//
|
||||
// Removal of the processor from the CPU list is pending until all SMI handlers are finished
|
||||
//
|
||||
gSmmCpuPrivate->Operation[ProcessorNumber] = SmmCpuRemove;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This return the handle number for the calling processor.
|
||||
|
||||
@param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param[out] ProcessorNumber The handle number of currently executing processor.
|
||||
|
||||
@retval EFI_SUCCESS The current processor handle number was returned
|
||||
in ProcessorNumber.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmWhoAmI (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
OUT UINTN *ProcessorNumber
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINT64 ApicId;
|
||||
|
||||
//
|
||||
// Check parameter
|
||||
//
|
||||
if (ProcessorNumber == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ApicId = GetApicId ();
|
||||
|
||||
for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
|
||||
if (gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == ApicId) {
|
||||
*ProcessorNumber = Index;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
//
|
||||
// This should not happen
|
||||
//
|
||||
ASSERT (FALSE);
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
Update the SMM CPU list per the pending operation.
|
||||
|
||||
This function is called after return from SMI handlers.
|
||||
**/
|
||||
VOID
|
||||
SmmCpuUpdate (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
|
||||
//
|
||||
// Handle pending BSP switch operations
|
||||
//
|
||||
for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
|
||||
if (gSmmCpuPrivate->Operation[Index] == SmmCpuSwitchBsp) {
|
||||
gSmmCpuPrivate->Operation[Index] = SmmCpuNone;
|
||||
mSmmMpSyncData->SwitchBsp = TRUE;
|
||||
mSmmMpSyncData->CandidateBsp[Index] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Handle pending hot-add operations
|
||||
//
|
||||
for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
|
||||
if (gSmmCpuPrivate->Operation[Index] == SmmCpuAdd) {
|
||||
gSmmCpuPrivate->Operation[Index] = SmmCpuNone;
|
||||
mNumberOfCpus++;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Handle pending hot-remove operations
|
||||
//
|
||||
for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
|
||||
if (gSmmCpuPrivate->Operation[Index] == SmmCpuRemove) {
|
||||
gSmmCpuPrivate->Operation[Index] = SmmCpuNone;
|
||||
mNumberOfCpus--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Register exception handler.
|
||||
|
||||
@param This A pointer to the SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param ExceptionType Defines which interrupt or exception to hook. Type EFI_EXCEPTION_TYPE and
|
||||
the valid values for this parameter are defined in EFI_DEBUG_SUPPORT_PROTOCOL
|
||||
of the UEFI 2.0 specification.
|
||||
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
|
||||
that is called when a processor interrupt occurs.
|
||||
If this parameter is NULL, then the handler will be uninstalled.
|
||||
|
||||
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
|
||||
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was previously installed.
|
||||
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not previously installed.
|
||||
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmRegisterExceptionHandler (
|
||||
IN EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN EFI_EXCEPTION_TYPE ExceptionType,
|
||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
|
||||
)
|
||||
{
|
||||
return RegisterCpuInterruptHandler (ExceptionType, InterruptHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize SMM CPU Services.
|
||||
|
||||
It installs EFI SMM CPU Services Protocol.
|
||||
|
||||
@param ImageHandle The firmware allocated handle for the EFI image.
|
||||
|
||||
@retval EFI_SUCCESS EFI SMM CPU Services Protocol was installed successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
InitializeSmmCpuServices (
|
||||
IN EFI_HANDLE Handle
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = gSmst->SmmInstallProtocolInterface (
|
||||
&Handle,
|
||||
&gEfiSmmCpuServiceProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
&mSmmCpuService
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
/** @file
|
||||
Include file for SMM CPU Services protocol implementation.
|
||||
|
||||
Copyright (c) 2011 - 2015, Intel Corporation. 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_SERVICE_H_
|
||||
#define _CPU_SERVICE_H_
|
||||
|
||||
typedef enum {
|
||||
SmmCpuNone,
|
||||
SmmCpuAdd,
|
||||
SmmCpuRemove,
|
||||
SmmCpuSwitchBsp
|
||||
} SMM_CPU_OPERATION;
|
||||
|
||||
//
|
||||
// SMM CPU Service Protocol function prototypes.
|
||||
//
|
||||
|
||||
/**
|
||||
Gets processor information on the requested processor at the instant this call is made.
|
||||
|
||||
@param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param[in] ProcessorNumber The handle number of processor.
|
||||
@param[out] ProcessorInfoBuffer A pointer to the buffer where information for
|
||||
the requested processor is deposited.
|
||||
|
||||
@retval EFI_SUCCESS Processor information was returned.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
|
||||
@retval EFI_NOT_FOUND The processor with the handle specified by
|
||||
ProcessorNumber does not exist in the platform.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmGetProcessorInfo (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN UINTN ProcessorNumber,
|
||||
OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
|
||||
);
|
||||
|
||||
/**
|
||||
This service switches the requested AP to be the BSP since the next SMI.
|
||||
|
||||
@param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param[in] ProcessorNumber The handle number of AP that is to become the new BSP.
|
||||
|
||||
@retval EFI_SUCCESS BSP will be switched in next SMI.
|
||||
@retval EFI_UNSUPPORTED Switching the BSP or a processor to be hot-removed is not supported.
|
||||
@retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmSwitchBsp (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN UINTN ProcessorNumber
|
||||
);
|
||||
|
||||
/**
|
||||
Notify that a processor was hot-added.
|
||||
|
||||
@param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param[in] ProcessorId Local APIC ID of the hot-added processor.
|
||||
@param[out] ProcessorNumber The handle number of the hot-added processor.
|
||||
|
||||
@retval EFI_SUCCESS The hot-addition of the specified processors was successfully notified.
|
||||
@retval EFI_UNSUPPORTED Hot addition of processor is not supported.
|
||||
@retval EFI_NOT_FOUND The processor with the handle specified by ProcessorNumber does not exist.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
|
||||
@retval EFI_ALREADY_STARTED The processor is already online in the system.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmAddProcessor (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN UINT64 ProcessorId,
|
||||
OUT UINTN *ProcessorNumber
|
||||
);
|
||||
|
||||
/**
|
||||
Notify that a processor was hot-removed.
|
||||
|
||||
@param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param[in] ProcessorNumber The handle number of the hot-added processor.
|
||||
|
||||
@retval EFI_SUCCESS The hot-removal of the specified processors was successfully notified.
|
||||
@retval EFI_UNSUPPORTED Hot removal of processor is not supported.
|
||||
@retval EFI_UNSUPPORTED Hot removal of BSP is not supported.
|
||||
@retval EFI_UNSUPPORTED Hot removal of a processor with pending hot-plug operation is not supported.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorNumber is invalid.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmRemoveProcessor (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN UINTN ProcessorNumber
|
||||
);
|
||||
|
||||
/**
|
||||
This return the handle number for the calling processor.
|
||||
|
||||
@param[in] This A pointer to the EFI_SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param[out] ProcessorNumber The handle number of currently executing processor.
|
||||
|
||||
@retval EFI_SUCCESS The current processor handle number was returned
|
||||
in ProcessorNumber.
|
||||
@retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmWhoAmI (
|
||||
IN CONST EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
OUT UINTN *ProcessorNumber
|
||||
);
|
||||
|
||||
/**
|
||||
Register exception handler.
|
||||
|
||||
@param This A pointer to the SMM_CPU_SERVICE_PROTOCOL instance.
|
||||
@param ExceptionType Defines which interrupt or exception to hook. Type EFI_EXCEPTION_TYPE and
|
||||
the valid values for this parameter are defined in EFI_DEBUG_SUPPORT_PROTOCOL
|
||||
of the UEFI 2.0 specification.
|
||||
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER
|
||||
that is called when a processor interrupt occurs.
|
||||
If this parameter is NULL, then the handler will be uninstalled.
|
||||
|
||||
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
|
||||
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was previously installed.
|
||||
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not previously installed.
|
||||
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmRegisterExceptionHandler (
|
||||
IN EFI_SMM_CPU_SERVICE_PROTOCOL *This,
|
||||
IN EFI_EXCEPTION_TYPE ExceptionType,
|
||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
|
||||
);
|
||||
|
||||
//
|
||||
// Internal function prototypes
|
||||
//
|
||||
|
||||
/**
|
||||
Update the SMM CPU list per the pending operation.
|
||||
|
||||
This function is called after return from SMI handlers.
|
||||
**/
|
||||
VOID
|
||||
SmmCpuUpdate (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize SMM CPU Services.
|
||||
|
||||
It installs EFI SMM CPU Services Protocol.
|
||||
|
||||
@param ImageHandle The firmware allocated handle for the EFI image.
|
||||
|
||||
@retval EFI_SUCCESS EFI SMM CPU Services Protocol was installed successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
InitializeSmmCpuServices (
|
||||
IN EFI_HANDLE Handle
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,165 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2006 - 2015, Intel Corporation. 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.
|
||||
#
|
||||
# Module Name:
|
||||
#
|
||||
# MpFuncs.S
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
# This is the assembly code for Multi-processor S3 support
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
.equ VacantFlag, 0x0
|
||||
.equ NotVacantFlag, 0xff
|
||||
|
||||
.equ LockLocation, RendezvousFunnelProcEnd - RendezvousFunnelProcStart
|
||||
.equ StackStart, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x04
|
||||
.equ StackSize, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x08
|
||||
.equ RendezvousProc, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x0C
|
||||
.equ GdtrProfile, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x10
|
||||
.equ IdtrProfile, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x16
|
||||
.equ BufferStart, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x1C
|
||||
|
||||
#-------------------------------------------------------------------------------------
|
||||
#RendezvousFunnelProc procedure follows. All APs execute their procedure. This
|
||||
#procedure serializes all the AP processors through an Init sequence. It must be
|
||||
#noted that APs arrive here very raw...ie: real mode, no stack.
|
||||
#ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
|
||||
#IS IN MACHINE CODE.
|
||||
#-------------------------------------------------------------------------------------
|
||||
#RendezvousFunnelProc (&WakeUpBuffer,MemAddress);
|
||||
|
||||
ASM_GLOBAL ASM_PFX(RendezvousFunnelProc)
|
||||
ASM_PFX(RendezvousFunnelProc):
|
||||
RendezvousFunnelProcStart:
|
||||
|
||||
# At this point CS = 0x(vv00) and ip= 0x0.
|
||||
|
||||
.byte 0x8c,0xc8 # mov ax, cs
|
||||
.byte 0x8e,0xd8 # mov ds, ax
|
||||
.byte 0x8e,0xc0 # mov es, ax
|
||||
.byte 0x8e,0xd0 # mov ss, ax
|
||||
.byte 0x33,0xc0 # xor ax, ax
|
||||
.byte 0x8e,0xe0 # mov fs, ax
|
||||
.byte 0x8e,0xe8 # mov gs, ax
|
||||
|
||||
flat32Start:
|
||||
|
||||
.byte 0xBE
|
||||
.word BufferStart
|
||||
.byte 0x66,0x8B,0x14 # mov edx,dword ptr [si] ; EDX is keeping the start address of wakeup buffer
|
||||
|
||||
.byte 0xBE
|
||||
.word GdtrProfile
|
||||
.byte 0x66 # db 66h
|
||||
.byte 0x2E,0xF,0x1,0x14 # lgdt fword ptr cs:[si]
|
||||
|
||||
.byte 0xBE
|
||||
.word IdtrProfile
|
||||
.byte 0x66 # db 66h
|
||||
.byte 0x2E,0xF,0x1,0x1C # lidt fword ptr cs:[si]
|
||||
|
||||
.byte 0x33,0xC0 # xor ax, ax
|
||||
.byte 0x8E,0xD8 # mov ds, ax
|
||||
|
||||
.byte 0xF,0x20,0xC0 # mov eax, cr0 ; Get control register 0
|
||||
.byte 0x66,0x83,0xC8,0x1 # or eax, 000000001h ; Set PE bit (bit #0)
|
||||
.byte 0xF,0x22,0xC0 # mov cr0, eax
|
||||
|
||||
FLAT32_JUMP:
|
||||
|
||||
.byte 0x66,0x67,0xEA # far jump
|
||||
.long 0x0 # 32-bit offset
|
||||
.word 0x20 # 16-bit selector
|
||||
|
||||
PMODE_ENTRY: # protected mode entry point
|
||||
|
||||
movw $0x8,%ax
|
||||
.byte 0x66
|
||||
movw %ax,%ds
|
||||
.byte 0x66
|
||||
movw %ax,%es
|
||||
.byte 0x66
|
||||
movw %ax,%fs
|
||||
.byte 0x66
|
||||
movw %ax,%gs
|
||||
.byte 0x66
|
||||
movw %ax,%ss # Flat mode setup.
|
||||
|
||||
movl %edx,%esi
|
||||
|
||||
movl %esi,%edi
|
||||
addl $LockLocation, %edi
|
||||
movb $NotVacantFlag, %al
|
||||
TestLock:
|
||||
xchgb (%edi), %al
|
||||
cmpb $NotVacantFlag, %al
|
||||
jz TestLock
|
||||
|
||||
ProgramStack:
|
||||
|
||||
movl %esi,%edi
|
||||
addl $StackSize, %edi
|
||||
movl (%edi),%eax
|
||||
movl %esi,%edi
|
||||
addl $StackStart, %edi
|
||||
addl (%edi),%eax
|
||||
movl %eax,%esp
|
||||
movl %eax,(%edi)
|
||||
|
||||
Releaselock:
|
||||
|
||||
movb $VacantFlag, %al
|
||||
movl %esi,%edi
|
||||
addl $LockLocation, %edi
|
||||
xchgb (%edi), %al
|
||||
|
||||
#
|
||||
# Call assembly function to initialize FPU.
|
||||
#
|
||||
lea ASM_PFX(InitializeFloatingPointUnits), %ebx
|
||||
call *%ebx
|
||||
#
|
||||
# Call C Function
|
||||
#
|
||||
movl %esi,%edi
|
||||
addl $RendezvousProc, %edi
|
||||
movl (%edi),%eax
|
||||
|
||||
testl %eax,%eax
|
||||
jz GoToSleep
|
||||
call *%eax # Call C function
|
||||
|
||||
GoToSleep:
|
||||
cli
|
||||
hlt
|
||||
jmp GoToSleep
|
||||
|
||||
RendezvousFunnelProcEnd:
|
||||
#-------------------------------------------------------------------------------------
|
||||
# AsmGetAddressMap (&AddressMap);
|
||||
#-------------------------------------------------------------------------------------
|
||||
ASM_GLOBAL ASM_PFX(AsmGetAddressMap)
|
||||
ASM_PFX(AsmGetAddressMap):
|
||||
|
||||
pushal
|
||||
movl %esp,%ebp
|
||||
|
||||
movl 0x24(%ebp), %ebx
|
||||
movl $RendezvousFunnelProcStart, (%ebx)
|
||||
movl $(PMODE_ENTRY - RendezvousFunnelProcStart), 0x4(%ebx)
|
||||
movl $(FLAT32_JUMP - RendezvousFunnelProcStart), 0x8(%ebx)
|
||||
movl $(RendezvousFunnelProcEnd - RendezvousFunnelProcStart), 0x0c(%ebx)
|
||||
|
||||
popal
|
||||
ret
|
|
@ -0,0 +1,168 @@
|
|||
;------------------------------------------------------------------------------ ;
|
||||
; Copyright (c) 2006 - 2015, Intel Corporation. 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.
|
||||
;
|
||||
; Module Name:
|
||||
;
|
||||
; MpFuncs.asm
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; This is the assembly code for Multi-processor S3 support
|
||||
;
|
||||
;-------------------------------------------------------------------------------
|
||||
|
||||
.686p
|
||||
.model flat,C
|
||||
.code
|
||||
|
||||
EXTERN InitializeFloatingPointUnits:PROC
|
||||
|
||||
VacantFlag Equ 00h
|
||||
NotVacantFlag Equ 0ffh
|
||||
|
||||
LockLocation equ RendezvousFunnelProcEnd - RendezvousFunnelProcStart
|
||||
StackStart equ LockLocation + 4h
|
||||
StackSize equ LockLocation + 8h
|
||||
RendezvousProc equ LockLocation + 0Ch
|
||||
GdtrProfile equ LockLocation + 10h
|
||||
IdtrProfile equ LockLocation + 16h
|
||||
BufferStart equ LockLocation + 1Ch
|
||||
|
||||
;-------------------------------------------------------------------------------------
|
||||
;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
|
||||
;procedure serializes all the AP processors through an Init sequence. It must be
|
||||
;noted that APs arrive here very raw...ie: real mode, no stack.
|
||||
;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
|
||||
;IS IN MACHINE CODE.
|
||||
;-------------------------------------------------------------------------------------
|
||||
;RendezvousFunnelProc (&WakeUpBuffer,MemAddress);
|
||||
|
||||
RendezvousFunnelProc PROC near C PUBLIC
|
||||
RendezvousFunnelProcStart::
|
||||
|
||||
; At this point CS = 0x(vv00) and ip= 0x0.
|
||||
|
||||
db 8ch, 0c8h ; mov ax, cs
|
||||
db 8eh, 0d8h ; mov ds, ax
|
||||
db 8eh, 0c0h ; mov es, ax
|
||||
db 8eh, 0d0h ; mov ss, ax
|
||||
db 33h, 0c0h ; xor ax, ax
|
||||
db 8eh, 0e0h ; mov fs, ax
|
||||
db 8eh, 0e8h ; mov gs, ax
|
||||
|
||||
flat32Start::
|
||||
|
||||
db 0BEh
|
||||
dw BufferStart ; mov si, BufferStart
|
||||
db 66h, 8Bh, 14h ; mov edx,dword ptr [si] ; EDX is keeping the start address of wakeup buffer
|
||||
|
||||
db 0BEh
|
||||
dw GdtrProfile ; mov si, GdtrProfile
|
||||
db 66h ; db 66h
|
||||
db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
|
||||
|
||||
db 0BEh
|
||||
dw IdtrProfile ; mov si, IdtrProfile
|
||||
db 66h ; db 66h
|
||||
db 2Eh, 0Fh, 01h, 1Ch ; lidt fword ptr cs:[si]
|
||||
|
||||
db 33h, 0C0h ; xor ax, ax
|
||||
db 8Eh, 0D8h ; mov ds, ax
|
||||
|
||||
db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Get control register 0
|
||||
db 66h, 83h, 0C8h, 01h ; or eax, 000000001h ; Set PE bit (bit #0)
|
||||
db 0Fh, 22h, 0C0h ; mov cr0, eax
|
||||
|
||||
FLAT32_JUMP::
|
||||
|
||||
db 66h, 67h, 0EAh ; far jump
|
||||
dd 0h ; 32-bit offset
|
||||
dw 20h ; 16-bit selector
|
||||
|
||||
PMODE_ENTRY:: ; protected mode entry point
|
||||
|
||||
mov ax, 8h
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax ; Flat mode setup.
|
||||
|
||||
mov esi, edx
|
||||
|
||||
mov edi, esi
|
||||
add edi, LockLocation
|
||||
mov al, NotVacantFlag
|
||||
TestLock::
|
||||
xchg byte ptr [edi], al
|
||||
cmp al, NotVacantFlag
|
||||
jz TestLock
|
||||
|
||||
ProgramStack::
|
||||
|
||||
mov edi, esi
|
||||
add edi, StackSize
|
||||
mov eax, dword ptr [edi]
|
||||
mov edi, esi
|
||||
add edi, StackStart
|
||||
add eax, dword ptr [edi]
|
||||
mov esp, eax
|
||||
mov dword ptr [edi], eax
|
||||
|
||||
Releaselock::
|
||||
|
||||
mov al, VacantFlag
|
||||
mov edi, esi
|
||||
add edi, LockLocation
|
||||
xchg byte ptr [edi], al
|
||||
|
||||
;
|
||||
; Call assembly function to initialize FPU.
|
||||
;
|
||||
mov ebx, InitializeFloatingPointUnits
|
||||
call ebx
|
||||
;
|
||||
; Call C Function
|
||||
;
|
||||
mov edi, esi
|
||||
add edi, RendezvousProc
|
||||
mov eax, dword ptr [edi]
|
||||
|
||||
test eax, eax
|
||||
jz GoToSleep
|
||||
call eax ; Call C function
|
||||
|
||||
GoToSleep::
|
||||
cli
|
||||
hlt
|
||||
jmp $-2
|
||||
|
||||
RendezvousFunnelProc ENDP
|
||||
RendezvousFunnelProcEnd::
|
||||
;-------------------------------------------------------------------------------------
|
||||
; AsmGetAddressMap (&AddressMap);
|
||||
;-------------------------------------------------------------------------------------
|
||||
AsmGetAddressMap PROC near C PUBLIC
|
||||
|
||||
pushad
|
||||
mov ebp,esp
|
||||
|
||||
mov ebx, dword ptr [ebp+24h]
|
||||
mov dword ptr [ebx], RendezvousFunnelProcStart
|
||||
mov dword ptr [ebx+4h], PMODE_ENTRY - RendezvousFunnelProcStart
|
||||
mov dword ptr [ebx+8h], FLAT32_JUMP - RendezvousFunnelProcStart
|
||||
mov dword ptr [ebx+0ch], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
|
||||
|
||||
popad
|
||||
ret
|
||||
|
||||
AsmGetAddressMap ENDP
|
||||
|
||||
END
|
|
@ -0,0 +1,132 @@
|
|||
/** @file
|
||||
Page table manipulation functions for IA-32 processors
|
||||
|
||||
Copyright (c) 2009 - 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "PiSmmCpuDxeSmm.h"
|
||||
|
||||
SPIN_LOCK mPFLock;
|
||||
|
||||
/**
|
||||
Create PageTable for SMM use.
|
||||
|
||||
@return PageTable Address
|
||||
|
||||
**/
|
||||
UINT32
|
||||
SmmInitPageTable (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN PageFaultHandlerHookAddress;
|
||||
IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
|
||||
|
||||
//
|
||||
// Initialize spin lock
|
||||
//
|
||||
InitializeSpinLock (&mPFLock);
|
||||
|
||||
if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
|
||||
//
|
||||
// Set own Page Fault entry instead of the default one, because SMM Profile
|
||||
// feature depends on IRET instruction to do Single Step
|
||||
//
|
||||
PageFaultHandlerHookAddress = (UINTN)PageFaultIdtHandlerSmmProfile;
|
||||
IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) gcSmiIdtr.Base;
|
||||
IdtEntry += EXCEPT_IA32_PAGE_FAULT;
|
||||
IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress;
|
||||
IdtEntry->Bits.Reserved_0 = 0;
|
||||
IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
|
||||
IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16);
|
||||
} else {
|
||||
//
|
||||
// Register SMM Page Fault Handler
|
||||
//
|
||||
SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_PAGE_FAULT, SmiPFHandler);
|
||||
}
|
||||
|
||||
//
|
||||
// Additional SMM IDT initialization for SMM stack guard
|
||||
//
|
||||
if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
|
||||
InitializeIDTSmmStackGuard ();
|
||||
}
|
||||
return Gen4GPageTable (0, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
Page Fault handler for SMM use.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SmiDefaultPFHandler (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
CpuDeadLoop ();
|
||||
}
|
||||
|
||||
/**
|
||||
ThePage Fault handler wrapper 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
|
||||
)
|
||||
{
|
||||
UINTN PFAddress;
|
||||
|
||||
ASSERT (InterruptType == EXCEPT_IA32_PAGE_FAULT);
|
||||
|
||||
AcquireSpinLock (&mPFLock);
|
||||
|
||||
PFAddress = AsmReadCr2 ();
|
||||
|
||||
if ((FeaturePcdGet (PcdCpuSmmStackGuard)) &&
|
||||
(PFAddress >= mCpuHotPlugData.SmrrBase) &&
|
||||
(PFAddress < (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize))) {
|
||||
DEBUG ((EFI_D_ERROR, "SMM stack overflow!\n"));
|
||||
CpuDeadLoop ();
|
||||
}
|
||||
|
||||
//
|
||||
// If a page fault occurs in SMM range
|
||||
//
|
||||
if ((PFAddress < mCpuHotPlugData.SmrrBase) ||
|
||||
(PFAddress >= mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) {
|
||||
if ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0) {
|
||||
DEBUG ((EFI_D_ERROR, "Code executed on IP(0x%x) out of SMM range after SMM is locked!\n", PFAddress));
|
||||
DEBUG_CODE (
|
||||
DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp);
|
||||
);
|
||||
CpuDeadLoop ();
|
||||
}
|
||||
}
|
||||
|
||||
if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
|
||||
SmmProfilePFHandler (
|
||||
SystemContext.SystemContextIa32->Eip,
|
||||
SystemContext.SystemContextIa32->ExceptionData
|
||||
);
|
||||
} else {
|
||||
SmiDefaultPFHandler ();
|
||||
}
|
||||
|
||||
ReleaseSpinLock (&mPFLock);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/** @file
|
||||
Semaphore mechanism to indicate to the BSP that an AP has exited SMM
|
||||
after SMBASE relocation.
|
||||
|
||||
Copyright (c) 2009 - 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "PiSmmCpuDxeSmm.h"
|
||||
|
||||
UINTN mSmmRelocationOriginalAddress;
|
||||
volatile BOOLEAN *mRebasedFlag;
|
||||
|
||||
/**
|
||||
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
|
||||
)
|
||||
{
|
||||
SMRAM_SAVE_STATE_MAP *CpuState;
|
||||
|
||||
mRebasedFlag = RebasedFlag;
|
||||
|
||||
CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
|
||||
mSmmRelocationOriginalAddress = (UINTN)HookReturnFromSmm (
|
||||
CpuIndex,
|
||||
CpuState,
|
||||
(UINT64)(UINTN)&SmmRelocationSemaphoreComplete,
|
||||
(UINT64)(UINTN)&SmmRelocationSemaphoreComplete
|
||||
);
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2009 - 2016, Intel Corporation. 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.
|
||||
#
|
||||
# Module Name:
|
||||
#
|
||||
# SmiEntry.S
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
# Code template of the SMI handler for a particular processor
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
ASM_GLOBAL ASM_PFX(gcSmiHandlerTemplate)
|
||||
ASM_GLOBAL ASM_PFX(gcSmiHandlerSize)
|
||||
ASM_GLOBAL ASM_PFX(gcSmiHandlerOffset)
|
||||
ASM_GLOBAL ASM_PFX(gSmiCr3)
|
||||
ASM_GLOBAL ASM_PFX(gSmiStack)
|
||||
ASM_GLOBAL ASM_PFX(gSmbase)
|
||||
ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
|
||||
ASM_GLOBAL ASM_PFX(gSmiHandlerIdtr)
|
||||
|
||||
.equ DSC_OFFSET, 0xfb00
|
||||
.equ DSC_GDTPTR, 0x48
|
||||
.equ DSC_GDTSIZ, 0x50
|
||||
.equ DSC_CS, 0x14
|
||||
.equ DSC_DS, 0x16
|
||||
.equ DSC_SS, 0x18
|
||||
.equ DSC_OTHERSEG, 0x1A
|
||||
|
||||
.equ PROTECT_MODE_CS, 0x08
|
||||
.equ PROTECT_MODE_DS, 0x20
|
||||
.equ TSS_SEGMENT, 0x40
|
||||
|
||||
.text
|
||||
|
||||
ASM_PFX(gcSmiHandlerOffset): .word _SmiHandler - _SmiEntryPoint + 0x8000
|
||||
|
||||
ASM_PFX(gcSmiHandlerTemplate):
|
||||
|
||||
_SmiEntryPoint:
|
||||
.byte 0xbb # mov bx, imm16
|
||||
.word _GdtDesc - _SmiEntryPoint + 0x8000
|
||||
.byte 0x2e,0xa1 # mov ax, cs:[offset16]
|
||||
.word DSC_OFFSET + DSC_GDTSIZ
|
||||
decl %eax
|
||||
movl %eax, %cs:(%edi) # mov cs:[bx], ax
|
||||
.byte 0x66,0x2e,0xa1 # mov eax, cs:[offset16]
|
||||
.word DSC_OFFSET + DSC_GDTPTR
|
||||
movw %ax, %cs:2(%edi)
|
||||
movw %ax, %bp # ebp = GDT base
|
||||
.byte 0x66
|
||||
lgdt %cs:(%edi)
|
||||
# Patch ProtectedMode Segment
|
||||
.byte 0xb8 # mov ax, imm16
|
||||
.word PROTECT_MODE_CS # set AX for segment directly
|
||||
movl %eax, %cs:-2(%edi) # mov cs:[bx - 2], ax
|
||||
# Patch ProtectedMode entry
|
||||
.byte 0x66, 0xbf # mov edi, SMBASE
|
||||
ASM_PFX(gSmbase): .space 4
|
||||
.byte 0x67
|
||||
lea ((Start32bit - _SmiEntryPoint) + 0x8000)(%edi), %ax
|
||||
movw %ax, %cs:-6(%edi)
|
||||
movl %cr0, %ebx
|
||||
.byte 0x66
|
||||
andl $0x9ffafff3, %ebx
|
||||
.byte 0x66
|
||||
orl $0x23, %ebx
|
||||
movl %ebx, %cr0
|
||||
.byte 0x66,0xea
|
||||
.space 4
|
||||
.space 2
|
||||
_GdtDesc: .space 4
|
||||
.space 2
|
||||
|
||||
Start32bit:
|
||||
movw $PROTECT_MODE_DS, %ax
|
||||
movl %eax,%ds
|
||||
movl %eax,%es
|
||||
movl %eax,%fs
|
||||
movl %eax,%gs
|
||||
movl %eax,%ss
|
||||
.byte 0xbc # mov esp, imm32
|
||||
ASM_PFX(gSmiStack): .space 4
|
||||
movl $ASM_PFX(gSmiHandlerIdtr), %eax
|
||||
lidt (%eax)
|
||||
jmp ProtFlatMode
|
||||
|
||||
ProtFlatMode:
|
||||
.byte 0xb8 # mov eax, imm32
|
||||
ASM_PFX(gSmiCr3): .space 4
|
||||
movl %eax, %cr3
|
||||
#
|
||||
# Need to test for CR4 specific bit support
|
||||
#
|
||||
movl $1, %eax
|
||||
cpuid # use CPUID to determine if specific CR4 bits are supported
|
||||
xorl %eax, %eax # Clear EAX
|
||||
testl $BIT2, %edx # Check for DE capabilities
|
||||
jz L8
|
||||
orl $BIT3, %eax
|
||||
L8:
|
||||
testl $BIT6, %edx # Check for PAE capabilities
|
||||
jz L9
|
||||
orl $BIT5, %eax
|
||||
L9:
|
||||
testl $BIT7, %edx # Check for MCE capabilities
|
||||
jz L10
|
||||
orl $BIT6, %eax
|
||||
L10:
|
||||
testl $BIT24, %edx # Check for FXSR capabilities
|
||||
jz L11
|
||||
orl $BIT9, %eax
|
||||
L11:
|
||||
testl $BIT25, %edx # Check for SSE capabilities
|
||||
jz L12
|
||||
orl $BIT10, %eax
|
||||
L12: # as cr4.PGE is not set here, refresh cr3
|
||||
movl %eax, %cr4 # in PreModifyMtrrs() to flush TLB.
|
||||
movl %cr0, %ebx
|
||||
orl $0x080010000, %ebx # enable paging + WP
|
||||
movl %ebx, %cr0
|
||||
leal DSC_OFFSET(%edi),%ebx
|
||||
movw DSC_DS(%ebx),%ax
|
||||
movl %eax, %ds
|
||||
movw DSC_OTHERSEG(%ebx),%ax
|
||||
movl %eax, %es
|
||||
movl %eax, %fs
|
||||
movl %eax, %gs
|
||||
movw DSC_SS(%ebx),%ax
|
||||
movl %eax, %ss
|
||||
|
||||
cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
|
||||
jz L5
|
||||
|
||||
# Load TSS
|
||||
movb $0x89, (TSS_SEGMENT + 5)(%ebp) # clear busy flag
|
||||
movl $TSS_SEGMENT, %eax
|
||||
ltrw %ax
|
||||
L5:
|
||||
|
||||
# jmp _SmiHandler # instruction is not needed
|
||||
|
||||
_SmiHandler:
|
||||
# below step is needed, because STM does not run above code.
|
||||
# we have to run below code to set IDT/CR0/CR4
|
||||
movl $ASM_PFX(gSmiHandlerIdtr), %eax
|
||||
lidt (%eax)
|
||||
movl %cr0, %eax
|
||||
orl $0x00000022, %eax
|
||||
orl $0x00010000, %eax # enable WP
|
||||
movl %eax, %cr0
|
||||
#
|
||||
# Need to test for CR4 specific bit support
|
||||
#
|
||||
movl $1, %eax
|
||||
cpuid # use CPUID to determine if specific CR4 bits are supported
|
||||
movl %cr4, %eax # init EAX
|
||||
testl $BIT2, %edx # Check for DE capabilities
|
||||
jz L28
|
||||
orl $BIT3, %eax
|
||||
L28:
|
||||
testl $BIT6, %edx # Check for PAE capabilities
|
||||
jz L29
|
||||
orl $BIT5, %eax
|
||||
L29:
|
||||
testl $BIT7, %edx # Check for MCE capabilities
|
||||
jz L30
|
||||
orl $BIT6, %eax
|
||||
L30:
|
||||
testl $BIT24, %edx # Check for FXSR capabilities
|
||||
jz L31
|
||||
orl $BIT9, %eax
|
||||
L31:
|
||||
testl $BIT25, %edx # Check for SSE capabilities
|
||||
jz L32
|
||||
orl $BIT10, %eax
|
||||
L32: # as cr4.PGE is not set here, refresh cr3
|
||||
movl %eax, %cr4 # in PreModifyMtrrs() to flush TLB.
|
||||
# STM init finish
|
||||
|
||||
movl (%esp), %ebx
|
||||
|
||||
pushl %ebx
|
||||
movl $ASM_PFX(CpuSmmDebugEntry), %eax
|
||||
call *%eax
|
||||
popl %ecx
|
||||
|
||||
pushl %ebx
|
||||
movl $ASM_PFX(SmiRendezvous), %eax
|
||||
call *%eax
|
||||
popl %ecx
|
||||
|
||||
pushl %ebx
|
||||
movl $ASM_PFX(CpuSmmDebugExit), %eax
|
||||
call *%eax
|
||||
popl %ecx
|
||||
|
||||
rsm
|
||||
|
||||
ASM_PFX(gcSmiHandlerSize): .word . - _SmiEntryPoint
|
|
@ -0,0 +1,219 @@
|
|||
;------------------------------------------------------------------------------ ;
|
||||
; Copyright (c) 2009 - 2016, Intel Corporation. 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.
|
||||
;
|
||||
; Module Name:
|
||||
;
|
||||
; SmiEntry.asm
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; Code template of the SMI handler for a particular processor
|
||||
;
|
||||
;-------------------------------------------------------------------------------
|
||||
|
||||
.686p
|
||||
.model flat,C
|
||||
.xmm
|
||||
|
||||
DSC_OFFSET EQU 0fb00h
|
||||
DSC_GDTPTR EQU 48h
|
||||
DSC_GDTSIZ EQU 50h
|
||||
DSC_CS EQU 14h
|
||||
DSC_DS EQU 16h
|
||||
DSC_SS EQU 18h
|
||||
DSC_OTHERSEG EQU 1Ah
|
||||
|
||||
PROTECT_MODE_CS EQU 08h
|
||||
PROTECT_MODE_DS EQU 20h
|
||||
TSS_SEGMENT EQU 40h
|
||||
|
||||
SmiRendezvous PROTO C
|
||||
CpuSmmDebugEntry PROTO C
|
||||
CpuSmmDebugExit PROTO C
|
||||
|
||||
EXTERNDEF gcSmiHandlerTemplate:BYTE
|
||||
EXTERNDEF gcSmiHandlerSize:WORD
|
||||
EXTERNDEF gcSmiHandlerOffset:WORD
|
||||
EXTERNDEF gSmiCr3:DWORD
|
||||
EXTERNDEF gSmiStack:DWORD
|
||||
EXTERNDEF gSmbase:DWORD
|
||||
EXTERNDEF FeaturePcdGet (PcdCpuSmmStackGuard):BYTE
|
||||
EXTERNDEF gSmiHandlerIdtr:FWORD
|
||||
|
||||
.const
|
||||
|
||||
gcSmiHandlerOffset DW _SmiHandler - _SmiEntryPoint + 8000h
|
||||
|
||||
.code
|
||||
|
||||
gcSmiHandlerTemplate LABEL BYTE
|
||||
|
||||
_SmiEntryPoint:
|
||||
DB 0bbh ; mov bx, imm16
|
||||
DW offset _GdtDesc - _SmiEntryPoint + 8000h
|
||||
DB 2eh, 0a1h ; mov ax, cs:[offset16]
|
||||
DW DSC_OFFSET + DSC_GDTSIZ
|
||||
dec eax
|
||||
mov cs:[edi], eax ; mov cs:[bx], ax
|
||||
DB 66h, 2eh, 0a1h ; mov eax, cs:[offset16]
|
||||
DW DSC_OFFSET + DSC_GDTPTR
|
||||
mov cs:[edi + 2], ax ; mov cs:[bx + 2], eax
|
||||
mov bp, ax ; ebp = GDT base
|
||||
DB 66h
|
||||
lgdt fword ptr cs:[edi] ; lgdt fword ptr cs:[bx]
|
||||
; Patch ProtectedMode Segment
|
||||
DB 0b8h ; mov ax, imm16
|
||||
DW PROTECT_MODE_CS ; set AX for segment directly
|
||||
mov cs:[edi - 2], eax ; mov cs:[bx - 2], ax
|
||||
; Patch ProtectedMode entry
|
||||
DB 66h, 0bfh ; mov edi, SMBASE
|
||||
gSmbase DD ?
|
||||
DB 67h
|
||||
lea ax, [edi + (@32bit - _SmiEntryPoint) + 8000h]
|
||||
mov cs:[edi - 6], ax ; mov cs:[bx - 6], eax
|
||||
mov ebx, cr0
|
||||
DB 66h
|
||||
and ebx, 9ffafff3h
|
||||
DB 66h
|
||||
or ebx, 23h
|
||||
mov cr0, ebx
|
||||
DB 66h, 0eah
|
||||
DD ?
|
||||
DW ?
|
||||
_GdtDesc FWORD ?
|
||||
|
||||
@32bit:
|
||||
mov ax, PROTECT_MODE_DS
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
DB 0bch ; mov esp, imm32
|
||||
gSmiStack DD ?
|
||||
mov eax, offset gSmiHandlerIdtr
|
||||
lidt fword ptr [eax]
|
||||
jmp ProtFlatMode
|
||||
|
||||
ProtFlatMode:
|
||||
DB 0b8h ; mov eax, imm32
|
||||
gSmiCr3 DD ?
|
||||
mov cr3, eax
|
||||
;
|
||||
; Need to test for CR4 specific bit support
|
||||
;
|
||||
mov eax, 1
|
||||
cpuid ; use CPUID to determine if specific CR4 bits are supported
|
||||
xor eax, eax ; Clear EAX
|
||||
test edx, BIT2 ; Check for DE capabilities
|
||||
jz @f
|
||||
or eax, BIT3
|
||||
@@:
|
||||
test edx, BIT6 ; Check for PAE capabilities
|
||||
jz @f
|
||||
or eax, BIT5
|
||||
@@:
|
||||
test edx, BIT7 ; Check for MCE capabilities
|
||||
jz @f
|
||||
or eax, BIT6
|
||||
@@:
|
||||
test edx, BIT24 ; Check for FXSR capabilities
|
||||
jz @f
|
||||
or eax, BIT9
|
||||
@@:
|
||||
test edx, BIT25 ; Check for SSE capabilities
|
||||
jz @f
|
||||
or eax, BIT10
|
||||
@@: ; as cr4.PGE is not set here, refresh cr3
|
||||
mov cr4, eax ; in PreModifyMtrrs() to flush TLB.
|
||||
mov ebx, cr0
|
||||
or ebx, 080010000h ; enable paging + WP
|
||||
mov cr0, ebx
|
||||
lea ebx, [edi + DSC_OFFSET]
|
||||
mov ax, [ebx + DSC_DS]
|
||||
mov ds, eax
|
||||
mov ax, [ebx + DSC_OTHERSEG]
|
||||
mov es, eax
|
||||
mov fs, eax
|
||||
mov gs, eax
|
||||
mov ax, [ebx + DSC_SS]
|
||||
mov ss, eax
|
||||
|
||||
cmp FeaturePcdGet (PcdCpuSmmStackGuard), 0
|
||||
jz @F
|
||||
|
||||
; Load TSS
|
||||
mov byte ptr [ebp + TSS_SEGMENT + 5], 89h ; clear busy flag
|
||||
mov eax, TSS_SEGMENT
|
||||
ltr ax
|
||||
@@:
|
||||
; jmp _SmiHandler ; instruction is not needed
|
||||
|
||||
_SmiHandler PROC
|
||||
; below step is needed, because STM does not run above code.
|
||||
; we have to run below code to set IDT/CR0/CR4
|
||||
mov eax, offset gSmiHandlerIdtr
|
||||
lidt fword ptr [eax]
|
||||
mov eax, cr0
|
||||
or eax, 00000022h
|
||||
or eax, 00010000h ; enable WP
|
||||
mov cr0, eax
|
||||
;
|
||||
; Need to test for CR4 specific bit support
|
||||
;
|
||||
mov eax, 1
|
||||
cpuid ; use CPUID to determine if specific CR4 bits are supported
|
||||
mov eax, cr4 ; init EAX
|
||||
test edx, BIT2 ; Check for DE capabilities
|
||||
jz @f
|
||||
or eax, BIT3
|
||||
@@:
|
||||
test edx, BIT6 ; Check for PAE capabilities
|
||||
jz @f
|
||||
or eax, BIT5
|
||||
@@:
|
||||
test edx, BIT7 ; Check for MCE capabilities
|
||||
jz @f
|
||||
or eax, BIT6
|
||||
@@:
|
||||
test edx, BIT24 ; Check for FXSR capabilities
|
||||
jz @f
|
||||
or eax, BIT9
|
||||
@@:
|
||||
test edx, BIT25 ; Check for SSE capabilities
|
||||
jz @f
|
||||
or eax, BIT10
|
||||
@@: ; as cr4.PGE is not set here, refresh cr3
|
||||
mov cr4, eax ; in PreModifyMtrrs() to flush TLB.
|
||||
; STM init finish
|
||||
|
||||
mov ebx, [esp] ; CPU Index
|
||||
|
||||
push ebx
|
||||
mov eax, CpuSmmDebugEntry
|
||||
call eax
|
||||
pop ecx
|
||||
|
||||
push ebx
|
||||
mov eax, SmiRendezvous
|
||||
call eax
|
||||
pop ecx
|
||||
|
||||
push ebx
|
||||
mov eax, CpuSmmDebugExit
|
||||
call eax
|
||||
pop ecx
|
||||
|
||||
rsm
|
||||
_SmiHandler ENDP
|
||||
|
||||
gcSmiHandlerSize DW $ - _SmiEntryPoint
|
||||
|
||||
END
|
|
@ -0,0 +1,956 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2009 - 2016, Intel Corporation. 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.
|
||||
#
|
||||
# Module Name:
|
||||
#
|
||||
# SmiException.S
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
# Exception handlers used in SM mode
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
ASM_GLOBAL ASM_PFX(SmiPFHandler)
|
||||
ASM_GLOBAL ASM_PFX(PageFaultStubFunction)
|
||||
ASM_GLOBAL ASM_PFX(gSmiMtrrs)
|
||||
ASM_GLOBAL ASM_PFX(gcSmiIdtr)
|
||||
ASM_GLOBAL ASM_PFX(gcSmiGdtr)
|
||||
ASM_GLOBAL ASM_PFX(gcPsd)
|
||||
ASM_GLOBAL ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))
|
||||
|
||||
ASM_GLOBAL ASM_PFX(SmmStmExceptionHandler)
|
||||
ASM_GLOBAL ASM_PFX(SmmStmSetup)
|
||||
ASM_GLOBAL ASM_PFX(SmmStmTeardown)
|
||||
|
||||
.data
|
||||
|
||||
NullSeg: .quad 0 # reserved by architecture
|
||||
CodeSeg32:
|
||||
.word -1 # LimitLow
|
||||
.word 0 # BaseLow
|
||||
.byte 0 # BaseMid
|
||||
.byte 0x9b
|
||||
.byte 0xcf # LimitHigh
|
||||
.byte 0 # BaseHigh
|
||||
ProtModeCodeSeg32:
|
||||
.word -1 # LimitLow
|
||||
.word 0 # BaseLow
|
||||
.byte 0 # BaseMid
|
||||
.byte 0x9b
|
||||
.byte 0xcf # LimitHigh
|
||||
.byte 0 # BaseHigh
|
||||
ProtModeSsSeg32:
|
||||
.word -1 # LimitLow
|
||||
.word 0 # BaseLow
|
||||
.byte 0 # BaseMid
|
||||
.byte 0x93
|
||||
.byte 0xcf # LimitHigh
|
||||
.byte 0 # BaseHigh
|
||||
DataSeg32:
|
||||
.word -1 # LimitLow
|
||||
.word 0 # BaseLow
|
||||
.byte 0 # BaseMid
|
||||
.byte 0x93
|
||||
.byte 0xcf # LimitHigh
|
||||
.byte 0 # BaseHigh
|
||||
CodeSeg16:
|
||||
.word -1
|
||||
.word 0
|
||||
.byte 0
|
||||
.byte 0x9b
|
||||
.byte 0x8f
|
||||
.byte 0
|
||||
DataSeg16:
|
||||
.word -1
|
||||
.word 0
|
||||
.byte 0
|
||||
.byte 0x93
|
||||
.byte 0x8f
|
||||
.byte 0
|
||||
CodeSeg64:
|
||||
.word -1 # LimitLow
|
||||
.word 0 # BaseLow
|
||||
.byte 0 # BaseMid
|
||||
.byte 0x9b
|
||||
.byte 0xaf # LimitHigh
|
||||
.byte 0 # BaseHigh
|
||||
.equ GDT_SIZE, .- NullSeg
|
||||
|
||||
TssSeg:
|
||||
.word TSS_DESC_SIZE -1 # LimitLow
|
||||
.word 0 # BaseLow
|
||||
.byte 0 # BaseMid
|
||||
.byte 0x89
|
||||
.byte 0x00 # LimitHigh
|
||||
.byte 0 # BaseHigh
|
||||
ExceptionTssSeg:
|
||||
.word TSS_DESC_SIZE - 1 # LimitLow
|
||||
.word 0 # BaseLow
|
||||
.byte 0 # BaseMid
|
||||
.byte 0x89
|
||||
.byte 0x00 # LimitHigh
|
||||
.byte 0 # BaseHigh
|
||||
|
||||
.equ CODE_SEL, CodeSeg32 - NullSeg
|
||||
.equ DATA_SEL, DataSeg32 - NullSeg
|
||||
.equ TSS_SEL, TssSeg - NullSeg
|
||||
.equ EXCEPTION_TSS_SEL, ExceptionTssSeg - NullSeg
|
||||
|
||||
# IA32 TSS fields
|
||||
.equ TSS_ESP0, 4
|
||||
.equ TSS_SS0, 8
|
||||
.equ TSS_ESP1, 12
|
||||
.equ TSS_SS1, 16
|
||||
.equ TSS_ESP2, 20
|
||||
.equ TSS_SS2, 24
|
||||
.equ TSS_CR3, 28
|
||||
.equ TSS_EIP, 32
|
||||
.equ TSS_EFLAGS, 36
|
||||
.equ TSS_EAX, 40
|
||||
.equ TSS_ECX, 44
|
||||
.equ TSS_EDX, 48
|
||||
.equ TSS_EBX, 52
|
||||
.equ TSS_ESP, 56
|
||||
.equ TSS_EBP, 60
|
||||
.equ TSS_ESI, 64
|
||||
.equ TSS_EDI, 68
|
||||
.equ TSS_ES, 72
|
||||
.equ TSS_CS, 76
|
||||
.equ TSS_SS, 80
|
||||
.equ TSS_DS, 84
|
||||
.equ TSS_FS, 88
|
||||
.equ TSS_GS, 92
|
||||
.equ TSS_LDT, 96
|
||||
|
||||
# Create 2 TSS segments just after GDT
|
||||
TssDescriptor:
|
||||
.word 0 # PreviousTaskLink
|
||||
.word 0 # Reserved
|
||||
.long 0 # ESP0
|
||||
.word 0 # SS0
|
||||
.word 0 # Reserved
|
||||
.long 0 # ESP1
|
||||
.word 0 # SS1
|
||||
.word 0 # Reserved
|
||||
.long 0 # ESP2
|
||||
.word 0 # SS2
|
||||
.word 0 # Reserved
|
||||
.long 0 # CR3
|
||||
.long 0 # EIP
|
||||
.long 0 # EFLAGS
|
||||
.long 0 # EAX
|
||||
.long 0 # ECX
|
||||
.long 0 # EDX
|
||||
.long 0 # EBX
|
||||
.long 0 # ESP
|
||||
.long 0 # EBP
|
||||
.long 0 # ESI
|
||||
.long 0 # EDI
|
||||
.word 0 # ES
|
||||
.word 0 # Reserved
|
||||
.word 0 # CS
|
||||
.word 0 # Reserved
|
||||
.word 0 # SS
|
||||
.word 0 # Reserved
|
||||
.word 0 # DS
|
||||
.word 0 # Reserved
|
||||
.word 0 # FS
|
||||
.word 0 # Reserved
|
||||
.word 0 # GS
|
||||
.word 0 # Reserved
|
||||
.word 0 # LDT Selector
|
||||
.word 0 # Reserved
|
||||
.word 0 # T
|
||||
.word 0 # I/O Map Base
|
||||
.equ TSS_DESC_SIZE, . - TssDescriptor
|
||||
|
||||
ExceptionTssDescriptor:
|
||||
.word 0 # PreviousTaskLink
|
||||
.word 0 # Reserved
|
||||
.long 0 # ESP0
|
||||
.word 0 # SS0
|
||||
.word 0 # Reserved
|
||||
.long 0 # ESP1
|
||||
.word 0 # SS1
|
||||
.word 0 # Reserved
|
||||
.long 0 # ESP2
|
||||
.word 0 # SS2
|
||||
.word 0 # Reserved
|
||||
.long 0 # CR3
|
||||
.long PFHandlerEntry # EIP
|
||||
.long 00000002 # EFLAGS
|
||||
.long 0 # EAX
|
||||
.long 0 # ECX
|
||||
.long 0 # EDX
|
||||
.long 0 # EBX
|
||||
.long 0 # ESP
|
||||
.long 0 # EBP
|
||||
.long 0 # ESI
|
||||
.long 0 # EDI
|
||||
.word DATA_SEL # ES
|
||||
.word 0 # Reserved
|
||||
.word CODE_SEL # CS
|
||||
.word 0 # Reserved
|
||||
.word DATA_SEL # SS
|
||||
.word 0 # Reserved
|
||||
.word DATA_SEL # DS
|
||||
.word 0 # Reserved
|
||||
.word DATA_SEL # FS
|
||||
.word 0 # Reserved
|
||||
.word DATA_SEL # GS
|
||||
.word 0 # Reserved
|
||||
.word 0 # LDT Selector
|
||||
.word 0 # Reserved
|
||||
.word 0 # T
|
||||
.word 0 # I/O Map Base
|
||||
|
||||
ASM_PFX(gcPsd):
|
||||
.ascii "TXTPSSIG"
|
||||
.word PSD_SIZE
|
||||
.word 1 # Version
|
||||
.long 0 # LocalApicId
|
||||
.byte 0x5 # Cr4Pse;Cr4Pae;Intel64Mode;ExecutionDisableOutsideSmrr
|
||||
.byte 0 # BIOS to STM
|
||||
.byte 0 # STM to BIOS
|
||||
.byte 0
|
||||
.word CODE_SEL
|
||||
.word DATA_SEL
|
||||
.word DATA_SEL
|
||||
.word DATA_SEL
|
||||
.word 0
|
||||
.word 0
|
||||
.quad 0 # SmmCr3
|
||||
.long ASM_PFX(_OnStmSetup)
|
||||
.long 0
|
||||
.long ASM_PFX(_OnStmTeardown)
|
||||
.long 0
|
||||
.quad 0 # SmmSmiHandlerRip - SMM guest entrypoint
|
||||
.quad 0 # SmmSmiHandlerRsp
|
||||
.long NullSeg
|
||||
.long 0
|
||||
.long GDT_SIZE
|
||||
.long 0x80010100 # RequiredStmSmmRevId
|
||||
.long ASM_PFX(_OnException)
|
||||
.long 0
|
||||
.quad 0 # ExceptionStack
|
||||
.quad DATA_SEL
|
||||
.quad 0x1F # ExceptionFilter
|
||||
.long 0
|
||||
.long ASM_PFX(gSmiMtrrs)
|
||||
.long 0
|
||||
.quad 0 # BiosHwResourceRequirementsPtr
|
||||
.quad 0 # AcpiRsdp
|
||||
.byte 0 # PhysicalAddressBits
|
||||
.equ PSD_SIZE, . - ASM_PFX(gcPsd)
|
||||
|
||||
ASM_PFX(gcSmiGdtr): .word GDT_SIZE - 1
|
||||
.long NullSeg
|
||||
|
||||
ASM_PFX(gcSmiIdtr): .word IDT_SIZE - 1
|
||||
.long _SmiIDT
|
||||
|
||||
_SmiIDT:
|
||||
# The following segment repeats 32 times:
|
||||
# No. 1
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 2
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 3
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 4
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 5
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 6
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 7
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 8
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 9
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 10
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 11
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 12
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 13
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 14
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 15
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 16
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 17
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 18
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 19
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 20
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 21
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 22
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 23
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 24
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 25
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 26
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 27
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 28
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 29
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 30
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 31
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
# No. 32
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
|
||||
.equ IDT_SIZE, . - _SmiIDT
|
||||
|
||||
TaskGateDescriptor:
|
||||
.word 0 # Reserved
|
||||
.word EXCEPTION_TSS_SEL # TSS Segment selector
|
||||
.byte 0 # Reserved
|
||||
.byte 0x85 # Task Gate, present, DPL = 0
|
||||
.word 0 # Reserved
|
||||
|
||||
.text
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# PageFaultIdtHandlerSmmProfile is the entry point for all exceptions
|
||||
#
|
||||
# Stack:
|
||||
#+---------------------+
|
||||
#+ EFlags +
|
||||
#+---------------------+
|
||||
#+ CS +
|
||||
#+---------------------+
|
||||
#+ EIP +
|
||||
#+---------------------+
|
||||
#+ Error Code +
|
||||
#+---------------------+
|
||||
#+ Vector Number +
|
||||
#+---------------------+
|
||||
#+ EBP +
|
||||
#+---------------------+ <-- EBP
|
||||
#
|
||||
# RSP set to odd multiple of 8 means ErrCode PRESENT
|
||||
#------------------------------------------------------------------------------
|
||||
ASM_GLOBAL ASM_PFX(PageFaultIdtHandlerSmmProfile)
|
||||
ASM_PFX(PageFaultIdtHandlerSmmProfile):
|
||||
pushl $0x0e # Page Fault
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
|
||||
|
||||
#
|
||||
# Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
|
||||
# is 16-byte aligned
|
||||
#
|
||||
andl $0xfffffff0, %esp
|
||||
subl $12, %esp
|
||||
|
||||
## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
pushl %eax
|
||||
pushl %ecx
|
||||
pushl %edx
|
||||
pushl %ebx
|
||||
leal (6*4)(%ebp), %ecx
|
||||
pushl %ecx # ESP
|
||||
pushl (%ebp) # EBP
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
|
||||
## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
movl %ss, %eax
|
||||
pushl %eax
|
||||
movzwl (4*4)(%ebp), %eax
|
||||
pushl %eax
|
||||
movl %ds, %eax
|
||||
pushl %eax
|
||||
movl %es, %eax
|
||||
pushl %eax
|
||||
movl %fs, %eax
|
||||
pushl %eax
|
||||
movl %gs, %eax
|
||||
pushl %eax
|
||||
|
||||
## UINT32 Eip;
|
||||
movl (3*4)(%ebp), %eax
|
||||
pushl %eax
|
||||
|
||||
## UINT32 Gdtr[2], Idtr[2];
|
||||
subl $8, %esp
|
||||
sidt (%esp)
|
||||
movl 2(%esp), %eax
|
||||
xchgl (%esp), %eax
|
||||
andl $0xffff, %eax
|
||||
movl %eax, 4(%esp)
|
||||
|
||||
subl $8, %esp
|
||||
sgdt (%esp)
|
||||
movl 2(%esp), %eax
|
||||
xchgl (%esp), %eax
|
||||
andl $0xffff, %eax
|
||||
movl %eax, 4(%esp)
|
||||
|
||||
## UINT32 Ldtr, Tr;
|
||||
xorl %eax, %eax
|
||||
strw %ax
|
||||
pushl %eax
|
||||
sldtw %ax
|
||||
pushl %eax
|
||||
|
||||
## UINT32 EFlags;
|
||||
movl (5*4)(%ebp), %eax
|
||||
pushl %eax
|
||||
|
||||
## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
movl %cr4, %eax
|
||||
orl $0x208, %eax
|
||||
movl %eax, %cr4
|
||||
pushl %eax
|
||||
movl %cr3, %eax
|
||||
pushl %eax
|
||||
movl %cr2, %eax
|
||||
pushl %eax
|
||||
xorl %eax, %eax
|
||||
pushl %eax
|
||||
movl %cr0, %eax
|
||||
pushl %eax
|
||||
|
||||
## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
movl %dr7, %eax
|
||||
pushl %eax
|
||||
movl %dr6, %eax
|
||||
pushl %eax
|
||||
movl %dr3, %eax
|
||||
pushl %eax
|
||||
movl %dr2, %eax
|
||||
pushl %eax
|
||||
movl %dr1, %eax
|
||||
pushl %eax
|
||||
movl %dr0, %eax
|
||||
pushl %eax
|
||||
|
||||
## FX_SAVE_STATE_IA32 FxSaveState;
|
||||
subl $512, %esp
|
||||
movl %esp, %edi
|
||||
.byte 0x0f, 0xae, 0x07 #fxsave [edi]
|
||||
|
||||
# UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
|
||||
cld
|
||||
|
||||
## UINT32 ExceptionData;
|
||||
pushl (2*4)(%ebp)
|
||||
|
||||
## call into exception handler
|
||||
|
||||
## Prepare parameter and call
|
||||
movl %esp, %edx
|
||||
pushl %edx
|
||||
movl (1*4)(%ebp), %edx
|
||||
pushl %edx
|
||||
|
||||
#
|
||||
# Call External Exception Handler
|
||||
#
|
||||
movl $ASM_PFX(SmiPFHandler), %eax
|
||||
call *%eax
|
||||
addl $8, %esp
|
||||
jmp L4
|
||||
|
||||
L4:
|
||||
## UINT32 ExceptionData;
|
||||
addl $4, %esp
|
||||
|
||||
## FX_SAVE_STATE_IA32 FxSaveState;
|
||||
movl %esp, %esi
|
||||
.byte 0xf, 0xae, 0xe # fxrstor [esi]
|
||||
addl $512, %esp
|
||||
|
||||
## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
## Skip restoration of DRx registers to support debuggers
|
||||
## that set breakpoints in interrupt/exception context
|
||||
addl $4*6, %esp
|
||||
|
||||
## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
popl %eax
|
||||
movl %eax, %cr0
|
||||
addl $4, %esp # not for Cr1
|
||||
popl %eax
|
||||
movl %eax, %cr2
|
||||
popl %eax
|
||||
movl %eax, %cr3
|
||||
popl %eax
|
||||
movl %eax, %cr4
|
||||
|
||||
## UINT32 EFlags;
|
||||
popl (5*4)(%ebp)
|
||||
|
||||
## UINT32 Ldtr, Tr;
|
||||
## UINT32 Gdtr[2], Idtr[2];
|
||||
## Best not let anyone mess with these particular registers...
|
||||
addl $24, %esp
|
||||
|
||||
## UINT32 Eip;
|
||||
popl (3*4)(%ebp)
|
||||
|
||||
## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
## NOTE - modified segment registers could hang the debugger... We
|
||||
## could attempt to insulate ourselves against this possibility,
|
||||
## but that poses risks as well.
|
||||
##
|
||||
popl %gs
|
||||
popl %fs
|
||||
popl %es
|
||||
popl %ds
|
||||
popl (4*4)(%ebp)
|
||||
popl %ss
|
||||
|
||||
## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
popl %edi
|
||||
popl %esi
|
||||
addl $4, %esp # not for ebp
|
||||
addl $4, %esp # not for esp
|
||||
popl %ebx
|
||||
popl %edx
|
||||
popl %ecx
|
||||
popl %eax
|
||||
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
|
||||
# Enable TF bit after page fault handler runs
|
||||
btsl $8, 16(%esp) # EFLAGS
|
||||
|
||||
addl $8, %esp # skip INT# & ErrCode
|
||||
Return:
|
||||
iret
|
||||
#
|
||||
# Page Fault Exception Handler entry when SMM Stack Guard is enabled
|
||||
# Executiot starts here after a task switch
|
||||
#
|
||||
PFHandlerEntry:
|
||||
#
|
||||
# Get this processor's TSS
|
||||
#
|
||||
subl $8, %esp
|
||||
sgdt 2(%esp)
|
||||
movl 4(%esp), %eax # GDT base
|
||||
addl $8, %esp
|
||||
movl (TSS_SEL+2)(%eax), %ecx
|
||||
shll $8, %ecx
|
||||
movb (TSS_SEL+7)(%eax), %cl
|
||||
rorl $8, %ecx # ecx = TSS base
|
||||
|
||||
movl %esp, %ebp
|
||||
|
||||
#
|
||||
# Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
|
||||
# is 16-byte aligned
|
||||
#
|
||||
andl $0xfffffff0, %esp
|
||||
subl $12, %esp
|
||||
|
||||
## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
pushl TSS_EAX(%ecx)
|
||||
pushl TSS_ECX(%ecx)
|
||||
pushl TSS_EDX(%ecx)
|
||||
pushl TSS_EBX(%ecx)
|
||||
pushl TSS_ESP(%ecx)
|
||||
pushl TSS_EBP(%ecx)
|
||||
pushl TSS_ESI(%ecx)
|
||||
pushl TSS_EDI(%ecx)
|
||||
|
||||
## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
movzwl TSS_SS(%ecx), %eax
|
||||
pushl %eax
|
||||
movzwl TSS_CS(%ecx), %eax
|
||||
pushl %eax
|
||||
movzwl TSS_DS(%ecx), %eax
|
||||
pushl %eax
|
||||
movzwl TSS_ES(%ecx), %eax
|
||||
pushl %eax
|
||||
movzwl TSS_FS(%ecx), %eax
|
||||
pushl %eax
|
||||
movzwl TSS_GS(%ecx), %eax
|
||||
pushl %eax
|
||||
|
||||
## UINT32 Eip;
|
||||
pushl TSS_EIP(%ecx)
|
||||
|
||||
## UINT32 Gdtr[2], Idtr[2];
|
||||
subl $8, %esp
|
||||
sidt (%esp)
|
||||
movl 2(%esp), %eax
|
||||
xchgl (%esp), %eax
|
||||
andl $0xFFFF, %eax
|
||||
movl %eax, 4(%esp)
|
||||
|
||||
subl $8, %esp
|
||||
sgdt (%esp)
|
||||
movl 2(%esp), %eax
|
||||
xchgl (%esp), %eax
|
||||
andl $0xFFFF, %eax
|
||||
movl %eax, 4(%esp)
|
||||
|
||||
## UINT32 Ldtr, Tr;
|
||||
movl $TSS_SEL, %eax
|
||||
pushl %eax
|
||||
movzwl TSS_LDT(%ecx), %eax
|
||||
pushl %eax
|
||||
|
||||
## UINT32 EFlags;
|
||||
pushl TSS_EFLAGS(%ecx)
|
||||
|
||||
## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
movl %cr4, %eax
|
||||
orl $0x208, %eax
|
||||
movl %eax, %cr4
|
||||
pushl %eax
|
||||
movl %cr3, %eax
|
||||
pushl %eax
|
||||
movl %cr2, %eax
|
||||
pushl %eax
|
||||
xorl %eax, %eax
|
||||
pushl %eax
|
||||
movl %cr0, %eax
|
||||
pushl %eax
|
||||
|
||||
## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
movl %dr7, %eax
|
||||
pushl %eax
|
||||
movl %dr6, %eax
|
||||
pushl %eax
|
||||
movl %dr3, %eax
|
||||
pushl %eax
|
||||
movl %dr2, %eax
|
||||
pushl %eax
|
||||
movl %dr1, %eax
|
||||
pushl %eax
|
||||
movl %dr0, %eax
|
||||
pushl %eax
|
||||
|
||||
## FX_SAVE_STATE_IA32 FxSaveState;
|
||||
## Clear TS bit in CR0 to avoid Device Not Available Exception (#NM)
|
||||
## when executing fxsave/fxrstor instruction
|
||||
clts
|
||||
subl $512, %esp
|
||||
movl %esp, %edi
|
||||
.byte 0x0f, 0xae, 0x07 #fxsave [edi]
|
||||
|
||||
# UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
|
||||
cld
|
||||
|
||||
## UINT32 ExceptionData;
|
||||
pushl (%ebp)
|
||||
|
||||
## call into exception handler
|
||||
movl %ecx, %ebx
|
||||
movl $ASM_PFX(SmiPFHandler), %eax
|
||||
|
||||
## Prepare parameter and call
|
||||
movl %esp, %edx
|
||||
pushl %edx
|
||||
movl $14, %edx
|
||||
pushl %edx
|
||||
|
||||
#
|
||||
# Call External Exception Handler
|
||||
#
|
||||
call *%eax
|
||||
addl $8, %esp
|
||||
|
||||
movl %ebx, %ecx
|
||||
## UINT32 ExceptionData;
|
||||
addl $4, %esp
|
||||
|
||||
## FX_SAVE_STATE_IA32 FxSaveState;
|
||||
movl %esp, %esi
|
||||
.byte 0xf, 0xae, 0xe # fxrstor [esi]
|
||||
addl $512, %esp
|
||||
|
||||
## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
## Skip restoration of DRx registers to support debuggers
|
||||
## that set breakpoints in interrupt/exception context
|
||||
addl $4*6, %esp
|
||||
|
||||
## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
popl %eax
|
||||
movl %eax, %cr0
|
||||
addl $4, %esp # not for Cr1
|
||||
popl %eax
|
||||
movl %eax, %cr2
|
||||
popl %eax
|
||||
movl %eax, TSS_CR3(%ecx)
|
||||
popl %eax
|
||||
movl %eax, %cr4
|
||||
|
||||
## UINT32 EFlags;
|
||||
popl TSS_EFLAGS(%ecx)
|
||||
|
||||
## UINT32 Ldtr, Tr;
|
||||
## UINT32 Gdtr[2], Idtr[2];
|
||||
## Best not let anyone mess with these particular registers...
|
||||
addl $24, %esp
|
||||
|
||||
## UINT32 Eip;
|
||||
popl TSS_EIP(%ecx)
|
||||
|
||||
## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
## NOTE - modified segment registers could hang the debugger... We
|
||||
## could attempt to insulate ourselves against this possibility,
|
||||
## but that poses risks as well.
|
||||
##
|
||||
popl %eax
|
||||
movw %ax, TSS_GS(%ecx)
|
||||
popl %eax
|
||||
movw %ax, TSS_FS(%ecx)
|
||||
popl %eax
|
||||
movw %ax, TSS_ES(%ecx)
|
||||
popl %eax
|
||||
movw %ax, TSS_DS(%ecx)
|
||||
popl %eax
|
||||
movw %ax, TSS_CS(%ecx)
|
||||
popl %eax
|
||||
movw %ax, TSS_SS(%ecx)
|
||||
|
||||
## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
popl TSS_EDI(%ecx)
|
||||
popl TSS_ESI(%ecx)
|
||||
addl $4, %esp # not for ebp
|
||||
addl $4, %esp # not for esp
|
||||
popl TSS_EBX(%ecx)
|
||||
popl TSS_EDX(%ecx)
|
||||
popl TSS_ECX(%ecx)
|
||||
popl TSS_EAX(%ecx)
|
||||
|
||||
movl %ebp, %esp
|
||||
|
||||
# Set single step DB# if SMM profile is enabled and page fault exception happens
|
||||
cmpb $0, ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))
|
||||
jz Done2
|
||||
# Create return context for iret in stub function
|
||||
movl TSS_ESP(%ecx), %eax # Get old stack pointer
|
||||
movl TSS_EIP(%ecx), %ebx
|
||||
movl %ebx, -0xc(%eax) # create EIP in old stack
|
||||
movzwl TSS_CS(%ecx), %ebx
|
||||
movl %ebx, -0x8(%eax) # create CS in old stack
|
||||
movl TSS_EFLAGS(%ecx), %ebx
|
||||
btsl $8,%ebx
|
||||
movl %ebx, -0x4(%eax) # create eflags in old stack
|
||||
movl TSS_ESP(%ecx), %eax # Get old stack pointer
|
||||
subl $12, %eax # minus 12 byte
|
||||
movl %eax, TSS_ESP(%ecx) # Set new stack pointer
|
||||
|
||||
# Replace the EIP of interrupted task with stub function
|
||||
movl $ASM_PFX(PageFaultStubFunction), %eax
|
||||
movl %eax, TSS_EIP(%ecx)
|
||||
# Jump to the iret so next page fault handler as a task will start again after iret.
|
||||
|
||||
Done2:
|
||||
|
||||
addl $4, %esp # skip ErrCode
|
||||
|
||||
jmp Return
|
||||
|
||||
ASM_PFX(PageFaultStubFunction):
|
||||
#
|
||||
# we need clean TS bit in CR0 to execute
|
||||
# x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions.
|
||||
#
|
||||
clts
|
||||
iret
|
||||
|
||||
ASM_GLOBAL ASM_PFX(InitializeIDTSmmStackGuard)
|
||||
ASM_PFX(InitializeIDTSmmStackGuard):
|
||||
pushl %ebx
|
||||
#
|
||||
# If SMM Stack Guard feature is enabled, the Page Fault Exception entry in IDT
|
||||
# is a Task Gate Descriptor so that when a Page Fault Exception occurs,
|
||||
# the processors can use a known good stack in case stack ran out.
|
||||
#
|
||||
leal _SmiIDT + 14 * 8, %ebx
|
||||
leal TaskGateDescriptor, %edx
|
||||
movl (%edx), %eax
|
||||
movl %eax, (%ebx)
|
||||
movl 4(%edx), %eax
|
||||
movl %eax, 4(%ebx)
|
||||
|
||||
popl %ebx
|
||||
ret
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# SMM Exception handlers
|
||||
#------------------------------------------------------------------------------
|
||||
ASM_GLOBAL ASM_PFX(_OnException)
|
||||
ASM_PFX(_OnException):
|
||||
movl %esp, %ecx
|
||||
pushl %ecx
|
||||
call ASM_PFX(SmmStmExceptionHandler)
|
||||
addl $4, %esp
|
||||
|
||||
movl %eax, %ebx
|
||||
movl $4, %eax
|
||||
.byte 0xf, 0x1, 0xc1 # VMCALL
|
||||
jmp .
|
||||
|
||||
ASM_GLOBAL ASM_PFX(_OnStmSetup)
|
||||
ASM_PFX(_OnStmSetup):
|
||||
call ASM_PFX(SmmStmSetup)
|
||||
rsm
|
||||
|
||||
ASM_GLOBAL ASM_PFX(_OnStmTeardown)
|
||||
ASM_PFX(_OnStmTeardown):
|
||||
call ASM_PFX(SmmStmTeardown)
|
||||
rsm
|
||||
|
|
@ -0,0 +1,780 @@
|
|||
;------------------------------------------------------------------------------ ;
|
||||
; Copyright (c) 2009 - 2016, Intel Corporation. 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.
|
||||
;
|
||||
; Module Name:
|
||||
;
|
||||
; SmiException.asm
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; Exception handlers used in SM mode
|
||||
;
|
||||
;-------------------------------------------------------------------------------
|
||||
|
||||
.686p
|
||||
.model flat,C
|
||||
|
||||
EXTERNDEF SmiPFHandler:PROC
|
||||
EXTERNDEF PageFaultStubFunction:PROC
|
||||
EXTERNDEF gSmiMtrrs:QWORD
|
||||
EXTERNDEF gcSmiIdtr:FWORD
|
||||
EXTERNDEF gcSmiGdtr:FWORD
|
||||
EXTERNDEF gcPsd:BYTE
|
||||
EXTERNDEF FeaturePcdGet (PcdCpuSmmProfileEnable):BYTE
|
||||
|
||||
SmmStmExceptionHandler PROTO
|
||||
SmmStmSetup PROTO
|
||||
SmmStmTeardown PROTO
|
||||
|
||||
.data
|
||||
|
||||
NullSeg DQ 0 ; reserved by architecture
|
||||
CodeSeg32 LABEL QWORD
|
||||
DW -1 ; LimitLow
|
||||
DW 0 ; BaseLow
|
||||
DB 0 ; BaseMid
|
||||
DB 9bh
|
||||
DB 0cfh ; LimitHigh
|
||||
DB 0 ; BaseHigh
|
||||
ProtModeCodeSeg32 LABEL QWORD
|
||||
DW -1 ; LimitLow
|
||||
DW 0 ; BaseLow
|
||||
DB 0 ; BaseMid
|
||||
DB 9bh
|
||||
DB 0cfh ; LimitHigh
|
||||
DB 0 ; BaseHigh
|
||||
ProtModeSsSeg32 LABEL QWORD
|
||||
DW -1 ; LimitLow
|
||||
DW 0 ; BaseLow
|
||||
DB 0 ; BaseMid
|
||||
DB 93h
|
||||
DB 0cfh ; LimitHigh
|
||||
DB 0 ; BaseHigh
|
||||
DataSeg32 LABEL QWORD
|
||||
DW -1 ; LimitLow
|
||||
DW 0 ; BaseLow
|
||||
DB 0 ; BaseMid
|
||||
DB 93h
|
||||
DB 0cfh ; LimitHigh
|
||||
DB 0 ; BaseHigh
|
||||
CodeSeg16 LABEL QWORD
|
||||
DW -1
|
||||
DW 0
|
||||
DB 0
|
||||
DB 9bh
|
||||
DB 8fh
|
||||
DB 0
|
||||
DataSeg16 LABEL QWORD
|
||||
DW -1
|
||||
DW 0
|
||||
DB 0
|
||||
DB 93h
|
||||
DB 8fh
|
||||
DB 0
|
||||
CodeSeg64 LABEL QWORD
|
||||
DW -1 ; LimitLow
|
||||
DW 0 ; BaseLow
|
||||
DB 0 ; BaseMid
|
||||
DB 9bh
|
||||
DB 0afh ; LimitHigh
|
||||
DB 0 ; BaseHigh
|
||||
GDT_SIZE = $ - offset NullSeg
|
||||
|
||||
TssSeg LABEL QWORD
|
||||
DW TSS_DESC_SIZE - 1 ; LimitLow
|
||||
DW 0 ; BaseLow
|
||||
DB 0 ; BaseMid
|
||||
DB 89h
|
||||
DB 00h ; LimitHigh
|
||||
DB 0 ; BaseHigh
|
||||
ExceptionTssSeg LABEL QWORD
|
||||
DW TSS_DESC_SIZE - 1 ; LimitLow
|
||||
DW 0 ; BaseLow
|
||||
DB 0 ; BaseMid
|
||||
DB 89h
|
||||
DB 00h ; LimitHigh
|
||||
DB 0 ; BaseHigh
|
||||
|
||||
CODE_SEL = offset CodeSeg32 - offset NullSeg
|
||||
DATA_SEL = offset DataSeg32 - offset NullSeg
|
||||
TSS_SEL = offset TssSeg - offset NullSeg
|
||||
EXCEPTION_TSS_SEL = offset ExceptionTssSeg - offset NullSeg
|
||||
|
||||
IA32_TSS STRUC
|
||||
DW ?
|
||||
DW ?
|
||||
ESP0 DD ?
|
||||
SS0 DW ?
|
||||
DW ?
|
||||
ESP1 DD ?
|
||||
SS1 DW ?
|
||||
DW ?
|
||||
ESP2 DD ?
|
||||
SS2 DW ?
|
||||
DW ?
|
||||
_CR3 DD ?
|
||||
EIP DD ?
|
||||
EFLAGS DD ?
|
||||
_EAX DD ?
|
||||
_ECX DD ?
|
||||
_EDX DD ?
|
||||
_EBX DD ?
|
||||
_ESP DD ?
|
||||
_EBP DD ?
|
||||
_ESI DD ?
|
||||
_EDI DD ?
|
||||
_ES DW ?
|
||||
DW ?
|
||||
_CS DW ?
|
||||
DW ?
|
||||
_SS DW ?
|
||||
DW ?
|
||||
_DS DW ?
|
||||
DW ?
|
||||
_FS DW ?
|
||||
DW ?
|
||||
_GS DW ?
|
||||
DW ?
|
||||
LDT DW ?
|
||||
DW ?
|
||||
DW ?
|
||||
DW ?
|
||||
IA32_TSS ENDS
|
||||
|
||||
; Create 2 TSS segments just after GDT
|
||||
TssDescriptor LABEL BYTE
|
||||
DW 0 ; PreviousTaskLink
|
||||
DW 0 ; Reserved
|
||||
DD 0 ; ESP0
|
||||
DW 0 ; SS0
|
||||
DW 0 ; Reserved
|
||||
DD 0 ; ESP1
|
||||
DW 0 ; SS1
|
||||
DW 0 ; Reserved
|
||||
DD 0 ; ESP2
|
||||
DW 0 ; SS2
|
||||
DW 0 ; Reserved
|
||||
DD 0 ; CR3
|
||||
DD 0 ; EIP
|
||||
DD 0 ; EFLAGS
|
||||
DD 0 ; EAX
|
||||
DD 0 ; ECX
|
||||
DD 0 ; EDX
|
||||
DD 0 ; EBX
|
||||
DD 0 ; ESP
|
||||
DD 0 ; EBP
|
||||
DD 0 ; ESI
|
||||
DD 0 ; EDI
|
||||
DW 0 ; ES
|
||||
DW 0 ; Reserved
|
||||
DW 0 ; CS
|
||||
DW 0 ; Reserved
|
||||
DW 0 ; SS
|
||||
DW 0 ; Reserved
|
||||
DW 0 ; DS
|
||||
DW 0 ; Reserved
|
||||
DW 0 ; FS
|
||||
DW 0 ; Reserved
|
||||
DW 0 ; GS
|
||||
DW 0 ; Reserved
|
||||
DW 0 ; LDT Selector
|
||||
DW 0 ; Reserved
|
||||
DW 0 ; T
|
||||
DW 0 ; I/O Map Base
|
||||
TSS_DESC_SIZE = $ - offset TssDescriptor
|
||||
|
||||
ExceptionTssDescriptor LABEL BYTE
|
||||
DW 0 ; PreviousTaskLink
|
||||
DW 0 ; Reserved
|
||||
DD 0 ; ESP0
|
||||
DW 0 ; SS0
|
||||
DW 0 ; Reserved
|
||||
DD 0 ; ESP1
|
||||
DW 0 ; SS1
|
||||
DW 0 ; Reserved
|
||||
DD 0 ; ESP2
|
||||
DW 0 ; SS2
|
||||
DW 0 ; Reserved
|
||||
DD 0 ; CR3
|
||||
DD offset PFHandlerEntry ; EIP
|
||||
DD 00000002 ; EFLAGS
|
||||
DD 0 ; EAX
|
||||
DD 0 ; ECX
|
||||
DD 0 ; EDX
|
||||
DD 0 ; EBX
|
||||
DD 0 ; ESP
|
||||
DD 0 ; EBP
|
||||
DD 0 ; ESI
|
||||
DD 0 ; EDI
|
||||
DW DATA_SEL ; ES
|
||||
DW 0 ; Reserved
|
||||
DW CODE_SEL ; CS
|
||||
DW 0 ; Reserved
|
||||
DW DATA_SEL ; SS
|
||||
DW 0 ; Reserved
|
||||
DW DATA_SEL ; DS
|
||||
DW 0 ; Reserved
|
||||
DW DATA_SEL ; FS
|
||||
DW 0 ; Reserved
|
||||
DW DATA_SEL ; GS
|
||||
DW 0 ; Reserved
|
||||
DW 0 ; LDT Selector
|
||||
DW 0 ; Reserved
|
||||
DW 0 ; T
|
||||
DW 0 ; I/O Map Base
|
||||
|
||||
gcPsd LABEL BYTE
|
||||
DB 'TXTPSSIG'
|
||||
DW PSD_SIZE
|
||||
DW 1 ; Version
|
||||
DD 0 ; LocalApicId
|
||||
DB 05h ; Cr4Pse;Cr4Pae;Intel64Mode;ExecutionDisableOutsideSmrr
|
||||
DB 0 ; BIOS to STM
|
||||
DB 0 ; STM to BIOS
|
||||
DB 0
|
||||
DW CODE_SEL
|
||||
DW DATA_SEL
|
||||
DW DATA_SEL
|
||||
DW DATA_SEL
|
||||
DW 0
|
||||
DW 0
|
||||
DQ 0 ; SmmCr3
|
||||
DQ _OnStmSetup
|
||||
DQ _OnStmTeardown
|
||||
DQ 0 ; SmmSmiHandlerRip - SMM guest entrypoint
|
||||
DQ 0 ; SmmSmiHandlerRsp
|
||||
DQ offset NullSeg
|
||||
DD GDT_SIZE
|
||||
DD 80010100h ; RequiredStmSmmRevId
|
||||
DQ _OnException
|
||||
DQ 0 ; ExceptionStack
|
||||
DW DATA_SEL
|
||||
DW 01Fh ; ExceptionFilter
|
||||
DD 0
|
||||
DQ offset gSmiMtrrs
|
||||
DQ 0 ; BiosHwResourceRequirementsPtr
|
||||
DQ 0 ; AcpiRsdp
|
||||
DB 0 ; PhysicalAddressBits
|
||||
PSD_SIZE = $ - offset gcPsd
|
||||
|
||||
gcSmiGdtr LABEL FWORD
|
||||
DW GDT_SIZE - 1
|
||||
DD offset NullSeg
|
||||
|
||||
gcSmiIdtr LABEL FWORD
|
||||
DW IDT_SIZE - 1
|
||||
DD offset _SmiIDT
|
||||
|
||||
_SmiIDT LABEL QWORD
|
||||
REPEAT 32
|
||||
DW 0 ; Offset 0:15
|
||||
DW CODE_SEL ; Segment selector
|
||||
DB 0 ; Unused
|
||||
DB 8eh ; Interrupt Gate, Present
|
||||
DW 0 ; Offset 16:31
|
||||
ENDM
|
||||
IDT_SIZE = $ - offset _SmiIDT
|
||||
|
||||
TaskGateDescriptor LABEL DWORD
|
||||
DW 0 ; Reserved
|
||||
DW EXCEPTION_TSS_SEL ; TSS Segment selector
|
||||
DB 0 ; Reserved
|
||||
DB 85h ; Task Gate, present, DPL = 0
|
||||
DW 0 ; Reserved
|
||||
|
||||
|
||||
.code
|
||||
;------------------------------------------------------------------------------
|
||||
; PageFaultIdtHandlerSmmProfile is the entry point page fault only
|
||||
;
|
||||
;
|
||||
; Stack:
|
||||
; +---------------------+
|
||||
; + EFlags +
|
||||
; +---------------------+
|
||||
; + CS +
|
||||
; +---------------------+
|
||||
; + EIP +
|
||||
; +---------------------+
|
||||
; + Error Code +
|
||||
; +---------------------+
|
||||
; + Vector Number +
|
||||
; +---------------------+
|
||||
; + EBP +
|
||||
; +---------------------+ <-- EBP
|
||||
;
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
PageFaultIdtHandlerSmmProfile PROC
|
||||
push 0eh ; Page Fault
|
||||
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
|
||||
;
|
||||
; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
|
||||
; is 16-byte aligned
|
||||
;
|
||||
and esp, 0fffffff0h
|
||||
sub esp, 12
|
||||
|
||||
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
push eax
|
||||
push ecx
|
||||
push edx
|
||||
push ebx
|
||||
lea ecx, [ebp + 6 * 4]
|
||||
push ecx ; ESP
|
||||
push dword ptr [ebp] ; EBP
|
||||
push esi
|
||||
push edi
|
||||
|
||||
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
mov eax, ss
|
||||
push eax
|
||||
movzx eax, word ptr [ebp + 4 * 4]
|
||||
push eax
|
||||
mov eax, ds
|
||||
push eax
|
||||
mov eax, es
|
||||
push eax
|
||||
mov eax, fs
|
||||
push eax
|
||||
mov eax, gs
|
||||
push eax
|
||||
|
||||
;; UINT32 Eip;
|
||||
mov eax, [ebp + 3 * 4]
|
||||
push eax
|
||||
|
||||
;; UINT32 Gdtr[2], Idtr[2];
|
||||
sub esp, 8
|
||||
sidt [esp]
|
||||
mov eax, [esp + 2]
|
||||
xchg eax, [esp]
|
||||
and eax, 0FFFFh
|
||||
mov [esp+4], eax
|
||||
|
||||
sub esp, 8
|
||||
sgdt [esp]
|
||||
mov eax, [esp + 2]
|
||||
xchg eax, [esp]
|
||||
and eax, 0FFFFh
|
||||
mov [esp+4], eax
|
||||
|
||||
;; UINT32 Ldtr, Tr;
|
||||
xor eax, eax
|
||||
str ax
|
||||
push eax
|
||||
sldt ax
|
||||
push eax
|
||||
|
||||
;; UINT32 EFlags;
|
||||
mov eax, [ebp + 5 * 4]
|
||||
push eax
|
||||
|
||||
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
mov eax, cr4
|
||||
or eax, 208h
|
||||
mov cr4, eax
|
||||
push eax
|
||||
mov eax, cr3
|
||||
push eax
|
||||
mov eax, cr2
|
||||
push eax
|
||||
xor eax, eax
|
||||
push eax
|
||||
mov eax, cr0
|
||||
push eax
|
||||
|
||||
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
mov eax, dr7
|
||||
push eax
|
||||
mov eax, dr6
|
||||
push eax
|
||||
mov eax, dr3
|
||||
push eax
|
||||
mov eax, dr2
|
||||
push eax
|
||||
mov eax, dr1
|
||||
push eax
|
||||
mov eax, dr0
|
||||
push eax
|
||||
|
||||
;; FX_SAVE_STATE_IA32 FxSaveState;
|
||||
sub esp, 512
|
||||
mov edi, esp
|
||||
db 0fh, 0aeh, 07h ;fxsave [edi]
|
||||
|
||||
; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
|
||||
cld
|
||||
|
||||
;; UINT32 ExceptionData;
|
||||
push dword ptr [ebp + 2 * 4]
|
||||
|
||||
;; call into exception handler
|
||||
|
||||
;; Prepare parameter and call
|
||||
mov edx, esp
|
||||
push edx
|
||||
mov edx, dword ptr [ebp + 1 * 4]
|
||||
push edx
|
||||
|
||||
;
|
||||
; Call External Exception Handler
|
||||
;
|
||||
mov eax, SmiPFHandler
|
||||
call eax
|
||||
add esp, 8
|
||||
|
||||
;; UINT32 ExceptionData;
|
||||
add esp, 4
|
||||
|
||||
;; FX_SAVE_STATE_IA32 FxSaveState;
|
||||
mov esi, esp
|
||||
db 0fh, 0aeh, 0eh ; fxrstor [esi]
|
||||
add esp, 512
|
||||
|
||||
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
;; Skip restoration of DRx registers to support debuggers
|
||||
;; that set breakpoint in interrupt/exception context
|
||||
add esp, 4 * 6
|
||||
|
||||
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
pop eax
|
||||
mov cr0, eax
|
||||
add esp, 4 ; not for Cr1
|
||||
pop eax
|
||||
mov cr2, eax
|
||||
pop eax
|
||||
mov cr3, eax
|
||||
pop eax
|
||||
mov cr4, eax
|
||||
|
||||
;; UINT32 EFlags;
|
||||
pop dword ptr [ebp + 5 * 4]
|
||||
|
||||
;; UINT32 Ldtr, Tr;
|
||||
;; UINT32 Gdtr[2], Idtr[2];
|
||||
;; Best not let anyone mess with these particular registers...
|
||||
add esp, 24
|
||||
|
||||
;; UINT32 Eip;
|
||||
pop dword ptr [ebp + 3 * 4]
|
||||
|
||||
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
;; NOTE - modified segment registers could hang the debugger... We
|
||||
;; could attempt to insulate ourselves against this possibility,
|
||||
;; but that poses risks as well.
|
||||
;;
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
pop dword ptr [ebp + 4 * 4]
|
||||
pop ss
|
||||
|
||||
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
pop edi
|
||||
pop esi
|
||||
add esp, 4 ; not for ebp
|
||||
add esp, 4 ; not for esp
|
||||
pop ebx
|
||||
pop edx
|
||||
pop ecx
|
||||
pop eax
|
||||
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
|
||||
; Enable TF bit after page fault handler runs
|
||||
bts dword ptr [esp + 16], 8 ; EFLAGS
|
||||
|
||||
add esp, 8 ; skip INT# & ErrCode
|
||||
Return:
|
||||
iretd
|
||||
;
|
||||
; Page Fault Exception Handler entry when SMM Stack Guard is enabled
|
||||
; Executiot starts here after a task switch
|
||||
;
|
||||
PFHandlerEntry::
|
||||
;
|
||||
; Get this processor's TSS
|
||||
;
|
||||
sub esp, 8
|
||||
sgdt [esp + 2]
|
||||
mov eax, [esp + 4] ; GDT base
|
||||
add esp, 8
|
||||
mov ecx, [eax + TSS_SEL + 2]
|
||||
shl ecx, 8
|
||||
mov cl, [eax + TSS_SEL + 7]
|
||||
ror ecx, 8 ; ecx = TSS base
|
||||
|
||||
mov ebp, esp
|
||||
|
||||
;
|
||||
; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
|
||||
; is 16-byte aligned
|
||||
;
|
||||
and esp, 0fffffff0h
|
||||
sub esp, 12
|
||||
|
||||
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
push (IA32_TSS ptr [ecx])._EAX
|
||||
push (IA32_TSS ptr [ecx])._ECX
|
||||
push (IA32_TSS ptr [ecx])._EDX
|
||||
push (IA32_TSS ptr [ecx])._EBX
|
||||
push (IA32_TSS ptr [ecx])._ESP
|
||||
push (IA32_TSS ptr [ecx])._EBP
|
||||
push (IA32_TSS ptr [ecx])._ESI
|
||||
push (IA32_TSS ptr [ecx])._EDI
|
||||
|
||||
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
movzx eax, (IA32_TSS ptr [ecx])._SS
|
||||
push eax
|
||||
movzx eax, (IA32_TSS ptr [ecx])._CS
|
||||
push eax
|
||||
movzx eax, (IA32_TSS ptr [ecx])._DS
|
||||
push eax
|
||||
movzx eax, (IA32_TSS ptr [ecx])._ES
|
||||
push eax
|
||||
movzx eax, (IA32_TSS ptr [ecx])._FS
|
||||
push eax
|
||||
movzx eax, (IA32_TSS ptr [ecx])._GS
|
||||
push eax
|
||||
|
||||
;; UINT32 Eip;
|
||||
push (IA32_TSS ptr [ecx]).EIP
|
||||
|
||||
;; UINT32 Gdtr[2], Idtr[2];
|
||||
sub esp, 8
|
||||
sidt [esp]
|
||||
mov eax, [esp + 2]
|
||||
xchg eax, [esp]
|
||||
and eax, 0FFFFh
|
||||
mov [esp+4], eax
|
||||
|
||||
sub esp, 8
|
||||
sgdt [esp]
|
||||
mov eax, [esp + 2]
|
||||
xchg eax, [esp]
|
||||
and eax, 0FFFFh
|
||||
mov [esp+4], eax
|
||||
|
||||
;; UINT32 Ldtr, Tr;
|
||||
mov eax, TSS_SEL
|
||||
push eax
|
||||
movzx eax, (IA32_TSS ptr [ecx]).LDT
|
||||
push eax
|
||||
|
||||
;; UINT32 EFlags;
|
||||
push (IA32_TSS ptr [ecx]).EFLAGS
|
||||
|
||||
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
mov eax, cr4
|
||||
or eax, 208h
|
||||
mov cr4, eax
|
||||
push eax
|
||||
mov eax, cr3
|
||||
push eax
|
||||
mov eax, cr2
|
||||
push eax
|
||||
xor eax, eax
|
||||
push eax
|
||||
mov eax, cr0
|
||||
push eax
|
||||
|
||||
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
mov eax, dr7
|
||||
push eax
|
||||
mov eax, dr6
|
||||
push eax
|
||||
mov eax, dr3
|
||||
push eax
|
||||
mov eax, dr2
|
||||
push eax
|
||||
mov eax, dr1
|
||||
push eax
|
||||
mov eax, dr0
|
||||
push eax
|
||||
|
||||
;; FX_SAVE_STATE_IA32 FxSaveState;
|
||||
;; Clear TS bit in CR0 to avoid Device Not Available Exception (#NM)
|
||||
;; when executing fxsave/fxrstor instruction
|
||||
clts
|
||||
sub esp, 512
|
||||
mov edi, esp
|
||||
db 0fh, 0aeh, 07h ;fxsave [edi]
|
||||
|
||||
; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
|
||||
cld
|
||||
|
||||
;; UINT32 ExceptionData;
|
||||
push dword ptr [ebp]
|
||||
|
||||
;; call into exception handler
|
||||
mov ebx, ecx
|
||||
mov eax, SmiPFHandler
|
||||
|
||||
;; Prepare parameter and call
|
||||
mov edx, esp
|
||||
push edx
|
||||
mov edx, 14
|
||||
push edx
|
||||
|
||||
;
|
||||
; Call External Exception Handler
|
||||
;
|
||||
call eax
|
||||
add esp, 8
|
||||
|
||||
mov ecx, ebx
|
||||
;; UINT32 ExceptionData;
|
||||
add esp, 4
|
||||
|
||||
;; FX_SAVE_STATE_IA32 FxSaveState;
|
||||
mov esi, esp
|
||||
db 0fh, 0aeh, 0eh ; fxrstor [esi]
|
||||
add esp, 512
|
||||
|
||||
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
;; Skip restoration of DRx registers to support debuggers
|
||||
;; that set breakpoints in interrupt/exception context
|
||||
add esp, 4 * 6
|
||||
|
||||
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
pop eax
|
||||
mov cr0, eax
|
||||
add esp, 4 ; not for Cr1
|
||||
pop eax
|
||||
mov cr2, eax
|
||||
pop eax
|
||||
mov (IA32_TSS ptr [ecx])._CR3, eax
|
||||
pop eax
|
||||
mov cr4, eax
|
||||
|
||||
;; UINT32 EFlags;
|
||||
pop (IA32_TSS ptr [ecx]).EFLAGS
|
||||
|
||||
;; UINT32 Ldtr, Tr;
|
||||
;; UINT32 Gdtr[2], Idtr[2];
|
||||
;; Best not let anyone mess with these particular registers...
|
||||
add esp, 24
|
||||
|
||||
;; UINT32 Eip;
|
||||
pop (IA32_TSS ptr [ecx]).EIP
|
||||
|
||||
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
;; NOTE - modified segment registers could hang the debugger... We
|
||||
;; could attempt to insulate ourselves against this possibility,
|
||||
;; but that poses risks as well.
|
||||
;;
|
||||
pop eax
|
||||
mov (IA32_TSS ptr [ecx])._GS, ax
|
||||
pop eax
|
||||
mov (IA32_TSS ptr [ecx])._FS, ax
|
||||
pop eax
|
||||
mov (IA32_TSS ptr [ecx])._ES, ax
|
||||
pop eax
|
||||
mov (IA32_TSS ptr [ecx])._DS, ax
|
||||
pop eax
|
||||
mov (IA32_TSS ptr [ecx])._CS, ax
|
||||
pop eax
|
||||
mov (IA32_TSS ptr [ecx])._SS, ax
|
||||
|
||||
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
pop (IA32_TSS ptr [ecx])._EDI
|
||||
pop (IA32_TSS ptr [ecx])._ESI
|
||||
add esp, 4 ; not for ebp
|
||||
add esp, 4 ; not for esp
|
||||
pop (IA32_TSS ptr [ecx])._EBX
|
||||
pop (IA32_TSS ptr [ecx])._EDX
|
||||
pop (IA32_TSS ptr [ecx])._ECX
|
||||
pop (IA32_TSS ptr [ecx])._EAX
|
||||
|
||||
mov esp, ebp
|
||||
|
||||
; Set single step DB# if SMM profile is enabled and page fault exception happens
|
||||
cmp FeaturePcdGet (PcdCpuSmmProfileEnable), 0
|
||||
jz @Done2
|
||||
|
||||
; Create return context for iretd in stub function
|
||||
mov eax, (IA32_TSS ptr [ecx])._ESP ; Get old stack pointer
|
||||
mov ebx, (IA32_TSS ptr [ecx]).EIP
|
||||
mov [eax - 0ch], ebx ; create EIP in old stack
|
||||
movzx ebx, (IA32_TSS ptr [ecx])._CS
|
||||
mov [eax - 08h], ebx ; create CS in old stack
|
||||
mov ebx, (IA32_TSS ptr [ecx]).EFLAGS
|
||||
bts ebx, 8
|
||||
mov [eax - 04h], ebx ; create eflags in old stack
|
||||
mov eax, (IA32_TSS ptr [ecx])._ESP ; Get old stack pointer
|
||||
sub eax, 0ch ; minus 12 byte
|
||||
mov (IA32_TSS ptr [ecx])._ESP, eax ; Set new stack pointer
|
||||
; Replace the EIP of interrupted task with stub function
|
||||
mov eax, PageFaultStubFunction
|
||||
mov (IA32_TSS ptr [ecx]).EIP, eax
|
||||
; Jump to the iretd so next page fault handler as a task will start again after iretd.
|
||||
@Done2:
|
||||
add esp, 4 ; skip ErrCode
|
||||
|
||||
jmp Return
|
||||
PageFaultIdtHandlerSmmProfile ENDP
|
||||
|
||||
PageFaultStubFunction PROC
|
||||
;
|
||||
; we need clean TS bit in CR0 to execute
|
||||
; x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions.
|
||||
;
|
||||
clts
|
||||
iretd
|
||||
PageFaultStubFunction ENDP
|
||||
|
||||
InitializeIDTSmmStackGuard PROC USES ebx
|
||||
;
|
||||
; If SMM Stack Guard feature is enabled, the Page Fault Exception entry in IDT
|
||||
; is a Task Gate Descriptor so that when a Page Fault Exception occurs,
|
||||
; the processors can use a known good stack in case stack is ran out.
|
||||
;
|
||||
lea ebx, _SmiIDT + 14 * 8
|
||||
lea edx, TaskGateDescriptor
|
||||
mov eax, [edx]
|
||||
mov [ebx], eax
|
||||
mov eax, [edx + 4]
|
||||
mov [ebx + 4], eax
|
||||
ret
|
||||
InitializeIDTSmmStackGuard ENDP
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; SMM Exception handlers
|
||||
;------------------------------------------------------------------------------
|
||||
_OnException PROC
|
||||
mov ecx, esp
|
||||
push ecx
|
||||
call SmmStmExceptionHandler
|
||||
add esp, 4
|
||||
|
||||
mov ebx, eax
|
||||
mov eax, 4
|
||||
DB 0fh, 01h, 0c1h ; VMCALL
|
||||
jmp $
|
||||
_OnException ENDP
|
||||
|
||||
_OnStmSetup PROC
|
||||
call SmmStmSetup
|
||||
rsm
|
||||
_OnStmSetup ENDP
|
||||
|
||||
_OnStmTeardown PROC
|
||||
call SmmStmTeardown
|
||||
rsm
|
||||
_OnStmTeardown ENDP
|
||||
|
||||
END
|
|
@ -0,0 +1,96 @@
|
|||
/** @file
|
||||
SMM CPU misc functions for Ia32 arch specific.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "PiSmmCpuDxeSmm.h"
|
||||
|
||||
/**
|
||||
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
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
IA32_SEGMENT_DESCRIPTOR *GdtDescriptor;
|
||||
UINTN TssBase;
|
||||
UINTN GdtTssTableSize;
|
||||
UINT8 *GdtTssTables;
|
||||
UINTN GdtTableStepSize;
|
||||
|
||||
if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
|
||||
//
|
||||
// For IA32 SMM, if SMM Stack Guard feature is enabled, we use 2 TSS.
|
||||
// in this case, we allocate separate GDT/TSS for each CPUs to avoid TSS load contention
|
||||
// on each SMI entry.
|
||||
//
|
||||
|
||||
//
|
||||
// Enlarge GDT to contain 2 TSS descriptors
|
||||
//
|
||||
gcSmiGdtr.Limit += (UINT16)(2 * sizeof (IA32_SEGMENT_DESCRIPTOR));
|
||||
|
||||
GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE * 2 + 7) & ~7; // 8 bytes aligned
|
||||
GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));
|
||||
ASSERT (GdtTssTables != NULL);
|
||||
GdtTableStepSize = GdtTssTableSize;
|
||||
|
||||
for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; Index++) {
|
||||
CopyMem (GdtTssTables + GdtTableStepSize * Index, (VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1 + TSS_SIZE * 2);
|
||||
//
|
||||
// Fixup TSS descriptors
|
||||
//
|
||||
TssBase = (UINTN)(GdtTssTables + GdtTableStepSize * Index + gcSmiGdtr.Limit + 1);
|
||||
GdtDescriptor = (IA32_SEGMENT_DESCRIPTOR *)(TssBase) - 2;
|
||||
GdtDescriptor->Bits.BaseLow = (UINT16)TssBase;
|
||||
GdtDescriptor->Bits.BaseMid = (UINT8)(TssBase >> 16);
|
||||
GdtDescriptor->Bits.BaseHigh = (UINT8)(TssBase >> 24);
|
||||
|
||||
TssBase += TSS_SIZE;
|
||||
GdtDescriptor++;
|
||||
GdtDescriptor->Bits.BaseLow = (UINT16)TssBase;
|
||||
GdtDescriptor->Bits.BaseMid = (UINT8)(TssBase >> 16);
|
||||
GdtDescriptor->Bits.BaseHigh = (UINT8)(TssBase >> 24);
|
||||
//
|
||||
// Fixup TSS segments
|
||||
//
|
||||
// ESP as known good stack
|
||||
//
|
||||
*(UINTN *)(TssBase + TSS_IA32_ESP_OFFSET) = mSmmStackArrayBase + EFI_PAGE_SIZE + Index * mSmmStackSize;
|
||||
*(UINT32 *)(TssBase + TSS_IA32_CR3_OFFSET) = Cr3;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// Just use original table, AllocatePage and copy them here to make sure GDTs are covered in page memory.
|
||||
//
|
||||
GdtTssTableSize = gcSmiGdtr.Limit + 1;
|
||||
GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));
|
||||
ASSERT (GdtTssTables != NULL);
|
||||
GdtTableStepSize = GdtTssTableSize;
|
||||
|
||||
for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; Index++) {
|
||||
CopyMem (GdtTssTables + GdtTableStepSize * Index, (VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1);
|
||||
}
|
||||
}
|
||||
|
||||
*GdtStepSize = GdtTableStepSize;
|
||||
return GdtTssTables;
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2009 - 2015, Intel Corporation. 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.
|
||||
#
|
||||
# Module Name:
|
||||
#
|
||||
# SmmInit.S
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
# Functions for relocating SMBASE's for all processors
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
ASM_GLOBAL ASM_PFX(gSmmCr0)
|
||||
ASM_GLOBAL ASM_PFX(gSmmCr3)
|
||||
ASM_GLOBAL ASM_PFX(gSmmCr4)
|
||||
ASM_GLOBAL ASM_PFX(gcSmmInitTemplate)
|
||||
ASM_GLOBAL ASM_PFX(gcSmmInitSize)
|
||||
ASM_GLOBAL ASM_PFX(gSmmJmpAddr)
|
||||
ASM_GLOBAL ASM_PFX(SmmRelocationSemaphoreComplete)
|
||||
ASM_GLOBAL ASM_PFX(gSmmInitStack)
|
||||
ASM_GLOBAL ASM_PFX(gcSmiInitGdtr)
|
||||
|
||||
.equ PROTECT_MODE_CS, 0x08
|
||||
.equ PROTECT_MODE_DS, 0x20
|
||||
|
||||
.text
|
||||
|
||||
ASM_PFX(gcSmiInitGdtr):
|
||||
.word 0
|
||||
.quad 0
|
||||
|
||||
SmmStartup:
|
||||
.byte 0x66,0xb8
|
||||
ASM_PFX(gSmmCr3): .space 4
|
||||
movl %eax, %cr3
|
||||
.byte 0x67,0x66
|
||||
lgdt %cs:(ASM_PFX(gcSmiInitGdtr) - SmmStartup)(%ebp)
|
||||
.byte 0x66,0xb8
|
||||
ASM_PFX(gSmmCr4): .space 4
|
||||
movl %eax, %cr4
|
||||
.byte 0x66,0xb8
|
||||
ASM_PFX(gSmmCr0): .space 4
|
||||
.byte 0xbf, PROTECT_MODE_DS, 0 # mov di, PROTECT_MODE_DS
|
||||
movl %eax, %cr0
|
||||
.byte 0x66,0xea # jmp far [ptr48]
|
||||
ASM_PFX(gSmmJmpAddr): .long Start32bit
|
||||
.word PROTECT_MODE_CS
|
||||
Start32bit:
|
||||
movl %edi,%ds
|
||||
movl %edi,%es
|
||||
movl %edi,%fs
|
||||
movl %edi,%gs
|
||||
movl %edi,%ss
|
||||
.byte 0xbc # mov esp, imm32
|
||||
ASM_PFX(gSmmInitStack): .space 4
|
||||
call ASM_PFX(SmmInitHandler)
|
||||
rsm
|
||||
|
||||
ASM_PFX(gcSmmInitTemplate):
|
||||
|
||||
_SmmInitTemplate:
|
||||
.byte 0x66
|
||||
movl $SmmStartup, %ebp
|
||||
.byte 0x66, 0x81, 0xed, 0, 0, 3, 0 # sub ebp, 0x30000
|
||||
jmp *%bp # jmp ebp actually
|
||||
|
||||
ASM_PFX(gcSmmInitSize): .word . - ASM_PFX(gcSmmInitTemplate)
|
||||
|
||||
|
||||
ASM_PFX(SmmRelocationSemaphoreComplete):
|
||||
pushl %eax
|
||||
movl ASM_PFX(mRebasedFlag), %eax
|
||||
movb $1, (%eax)
|
||||
popl %eax
|
||||
jmp *ASM_PFX(mSmmRelocationOriginalAddress)
|
|
@ -0,0 +1,94 @@
|
|||
;------------------------------------------------------------------------------ ;
|
||||
; Copyright (c) 2009 - 2015, Intel Corporation. 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.
|
||||
;
|
||||
; Module Name:
|
||||
;
|
||||
; SmmInit.Asm
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; Functions for relocating SMBASE's for all processors
|
||||
;
|
||||
;-------------------------------------------------------------------------------
|
||||
|
||||
.686p
|
||||
.xmm
|
||||
.model flat,C
|
||||
|
||||
SmmInitHandler PROTO C
|
||||
|
||||
EXTERNDEF C gSmmCr0:DWORD
|
||||
EXTERNDEF C gSmmCr3:DWORD
|
||||
EXTERNDEF C gSmmCr4:DWORD
|
||||
EXTERNDEF C gcSmmInitTemplate:BYTE
|
||||
EXTERNDEF C gcSmmInitSize:WORD
|
||||
EXTERNDEF C gSmmJmpAddr:QWORD
|
||||
EXTERNDEF C mRebasedFlag:PTR BYTE
|
||||
EXTERNDEF C mSmmRelocationOriginalAddress:DWORD
|
||||
EXTERNDEF C gSmmInitStack:DWORD
|
||||
EXTERNDEF C gcSmiInitGdtr:FWORD
|
||||
|
||||
PROTECT_MODE_CS EQU 08h
|
||||
PROTECT_MODE_DS EQU 20h
|
||||
|
||||
.code
|
||||
|
||||
gcSmiInitGdtr LABEL FWORD
|
||||
DW 0
|
||||
DQ 0
|
||||
|
||||
SmmStartup PROC
|
||||
DB 66h, 0b8h
|
||||
gSmmCr3 DD ?
|
||||
mov cr3, eax
|
||||
DB 67h, 66h
|
||||
lgdt fword ptr cs:[ebp + (offset gcSmiInitGdtr - SmmStartup)]
|
||||
DB 66h, 0b8h
|
||||
gSmmCr4 DD ?
|
||||
mov cr4, eax
|
||||
DB 66h, 0b8h
|
||||
gSmmCr0 DD ?
|
||||
DB 0bfh, PROTECT_MODE_DS, 0 ; mov di, PROTECT_MODE_DS
|
||||
mov cr0, eax
|
||||
DB 66h, 0eah ; jmp far [ptr48]
|
||||
gSmmJmpAddr LABEL QWORD
|
||||
DD @32bit
|
||||
DW PROTECT_MODE_CS
|
||||
@32bit:
|
||||
mov ds, edi
|
||||
mov es, edi
|
||||
mov fs, edi
|
||||
mov gs, edi
|
||||
mov ss, edi
|
||||
DB 0bch ; mov esp, imm32
|
||||
gSmmInitStack DD ?
|
||||
call SmmInitHandler
|
||||
rsm
|
||||
SmmStartup ENDP
|
||||
|
||||
gcSmmInitTemplate LABEL BYTE
|
||||
|
||||
_SmmInitTemplate PROC
|
||||
DB 66h
|
||||
mov ebp, SmmStartup
|
||||
DB 66h, 81h, 0edh, 00h, 00h, 03h, 00 ; sub ebp, 30000h
|
||||
jmp bp ; jmp ebp actually
|
||||
_SmmInitTemplate ENDP
|
||||
|
||||
gcSmmInitSize DW $ - gcSmmInitTemplate
|
||||
|
||||
SmmRelocationSemaphoreComplete PROC
|
||||
push eax
|
||||
mov eax, mRebasedFlag
|
||||
mov byte ptr [eax], 1
|
||||
pop eax
|
||||
jmp [mSmmRelocationOriginalAddress]
|
||||
SmmRelocationSemaphoreComplete ENDP
|
||||
END
|
|
@ -0,0 +1,80 @@
|
|||
/** @file
|
||||
IA-32 processor specific functions to enable SMM profile.
|
||||
|
||||
Copyright (c) 2012 - 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "PiSmmCpuDxeSmm.h"
|
||||
#include "SmmProfileInternal.h"
|
||||
|
||||
/**
|
||||
Create SMM page table for S3 path.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitSmmS3Cr3 (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
mSmmS3ResumeState->SmmS3Cr3 = Gen4GPageTable (0, TRUE);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
Allocate pages for creating 4KB-page based on 2MB-page when page fault happens.
|
||||
32-bit firmware does not need it.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitPagesForPFHandler (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Update page table to map the memory correctly in order to make the instruction
|
||||
which caused page fault execute successfully. And it also save the original page
|
||||
table to be restored in single-step exception. 32-bit firmware does not need it.
|
||||
|
||||
@param PageTable PageTable Address.
|
||||
@param PFAddress The memory address which caused page fault exception.
|
||||
@param CpuIndex The index of the processor.
|
||||
@param ErrorCode The Error code of exception.
|
||||
@param IsValidPFAddress The flag indicates if SMM profile data need be added.
|
||||
|
||||
**/
|
||||
VOID
|
||||
RestorePageTableAbove4G (
|
||||
UINT64 *PageTable,
|
||||
UINT64 PFAddress,
|
||||
UINTN CpuIndex,
|
||||
UINTN ErrorCode,
|
||||
BOOLEAN *IsValidPFAddress
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Clear TF in FLAGS.
|
||||
|
||||
@param SystemContext A pointer to the processor context when
|
||||
the interrupt occurred on the processor.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ClearTrapFlag (
|
||||
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
||||
)
|
||||
{
|
||||
SystemContext.SystemContextIa32->Eflags &= (UINTN) ~BIT8;
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/** @file
|
||||
IA-32 processor specific header file to enable SMM profile.
|
||||
|
||||
Copyright (c) 2012 - 2015, Intel Corporation. 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 _SMM_PROFILE_ARCH_H_
|
||||
#define _SMM_PROFILE_ARCH_H_
|
||||
|
||||
#pragma pack (1)
|
||||
|
||||
typedef struct _MSR_DS_AREA_STRUCT {
|
||||
UINT32 BTSBufferBase;
|
||||
UINT32 BTSIndex;
|
||||
UINT32 BTSAbsoluteMaximum;
|
||||
UINT32 BTSInterruptThreshold;
|
||||
UINT32 PEBSBufferBase;
|
||||
UINT32 PEBSIndex;
|
||||
UINT32 PEBSAbsoluteMaximum;
|
||||
UINT32 PEBSInterruptThreshold;
|
||||
UINT32 PEBSCounterReset[4];
|
||||
UINT32 Reserved;
|
||||
} MSR_DS_AREA_STRUCT;
|
||||
|
||||
typedef struct _BRANCH_TRACE_RECORD {
|
||||
UINT32 LastBranchFrom;
|
||||
UINT32 LastBranchTo;
|
||||
UINT32 Rsvd0 : 4;
|
||||
UINT32 BranchPredicted : 1;
|
||||
UINT32 Rsvd1 : 27;
|
||||
} BRANCH_TRACE_RECORD;
|
||||
|
||||
typedef struct _PEBS_RECORD {
|
||||
UINT32 Eflags;
|
||||
UINT32 LinearIP;
|
||||
UINT32 Eax;
|
||||
UINT32 Ebx;
|
||||
UINT32 Ecx;
|
||||
UINT32 Edx;
|
||||
UINT32 Esi;
|
||||
UINT32 Edi;
|
||||
UINT32 Ebp;
|
||||
UINT32 Esp;
|
||||
} PEBS_RECORD;
|
||||
|
||||
#pragma pack ()
|
||||
|
||||
#define PHYSICAL_ADDRESS_MASK ((1ull << 32) - SIZE_4KB)
|
||||
|
||||
/**
|
||||
Update page table to map the memory correctly in order to make the instruction
|
||||
which caused page fault execute successfully. And it also save the original page
|
||||
table to be restored in single-step exception. 32-bit firmware does not need it.
|
||||
|
||||
@param PageTable PageTable Address.
|
||||
@param PFAddress The memory address which caused page fault exception.
|
||||
@param CpuIndex The index of the processor.
|
||||
@param ErrorCode The Error code of exception.
|
||||
@param IsValidPFAddress The flag indicates if SMM profile data need be added.
|
||||
|
||||
**/
|
||||
VOID
|
||||
RestorePageTableAbove4G (
|
||||
UINT64 *PageTable,
|
||||
UINT64 PFAddress,
|
||||
UINTN CpuIndex,
|
||||
UINTN ErrorCode,
|
||||
BOOLEAN *IsValidPFAddress
|
||||
);
|
||||
|
||||
/**
|
||||
Create SMM page table for S3 path.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitSmmS3Cr3 (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Allocate pages for creating 4KB-page based on 2MB-page when page fault happens.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitPagesForPFHandler (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif // _SMM_PROFILE_ARCH_H_
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,747 @@
|
|||
/** @file
|
||||
Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
|
||||
|
||||
Copyright (c) 2009 - 2016, Intel Corporation. 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/SmmEndOfDxe.h>
|
||||
#include <Protocol/SmmCpuService.h>
|
||||
|
||||
#include <Guid/AcpiS3Context.h>
|
||||
#include <Guid/MsegSmram.h>
|
||||
#include <Guid/Acpi.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 <StmApi.h>
|
||||
|
||||
#include "CpuService.h"
|
||||
#include "SmmProfile.h"
|
||||
#include "SmmStm.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_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)
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
//
|
||||
// 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 BOOLEAN mRestoreSmmConfigurationInS3;
|
||||
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;
|
||||
|
||||
typedef struct {
|
||||
SPIN_LOCK SpinLock;
|
||||
UINT32 MsrIndex;
|
||||
} MP_MSR_LOCK;
|
||||
|
||||
#define SMM_PSD_OFFSET 0xfb00
|
||||
|
||||
extern IA32_DESCRIPTOR gcSmiGdtr;
|
||||
extern IA32_DESCRIPTOR gcSmiIdtr;
|
||||
extern VOID *gcSmiIdtrPtr;
|
||||
extern CONST TXT_PROCESSOR_SMM_DESCRIPTOR gcPsd;
|
||||
extern UINT64 gPhyMask;
|
||||
extern ACPI_CPU_DATA mAcpiCpuData;
|
||||
extern SMM_DISPATCHER_MP_SYNC_DATA *mSmmMpSyncData;
|
||||
extern VOID *mGdtForAp;
|
||||
extern VOID *mIdtForAp;
|
||||
extern VOID *mMachineCheckHandlerForAp;
|
||||
extern UINTN mSmmStackArrayBase;
|
||||
extern UINTN mSmmStackArrayEnd;
|
||||
extern UINTN mSmmStackSize;
|
||||
extern EFI_SMM_CPU_SERVICE_PROTOCOL mSmmCpuService;
|
||||
extern IA32_DESCRIPTOR gcSmiInitGdtr;
|
||||
|
||||
/**
|
||||
Create 4G PageTable in SMRAM.
|
||||
|
||||
@param ExtraPages Additional page numbers besides for 4G memory
|
||||
@param Is32BitPageTable Whether the page table is 32-bit PAE
|
||||
@return PageTable Address
|
||||
|
||||
**/
|
||||
UINT32
|
||||
Gen4GPageTable (
|
||||
IN UINTN ExtraPages,
|
||||
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
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
/**
|
||||
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
|
||||
);
|
||||
|
||||
/**
|
||||
The function is invoked before SMBASE relocation in S3 path to restores CPU status.
|
||||
|
||||
The function is invoked before SMBASE relocation in S3 path. It does first time microcode load
|
||||
and restores MTRRs for both BSP and APs.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EarlyInitializeCpu (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
The function is invoked after SMBASE relocation in S3 path to restores CPU status.
|
||||
|
||||
The function is invoked after SMBASE relocation in S3 path. It restores configuration according to
|
||||
data saved by normal boot path for both BSP and APs.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitializeCpu (
|
||||
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
|
||||
);
|
||||
|
||||
/**
|
||||
Get the offset of the native SMI Handler.
|
||||
|
||||
@retval The offset of the native SMI Handler.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
GetSmiHandlerOffset (
|
||||
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 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
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,170 @@
|
|||
## @file
|
||||
# CPU SMM driver.
|
||||
#
|
||||
# This SMM driver performs SMM initialization, deploy SMM Entry Vector,
|
||||
# provides CPU specific services in SMM.
|
||||
#
|
||||
# Copyright (c) 2009 - 2016, Intel Corporation. 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = PiSmmCpuDxeSmmStm
|
||||
MODULE_UNI_FILE = PiSmmCpuDxeSmm.uni
|
||||
FILE_GUID = A3FF0EF5-0C28-42f5-B544-8C7DE1E80014
|
||||
MODULE_TYPE = DXE_SMM_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
PI_SPECIFICATION_VERSION = 0x0001000A
|
||||
ENTRY_POINT = PiCpuSmmEntry
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
PiSmmCpuDxeSmm.c
|
||||
PiSmmCpuDxeSmm.h
|
||||
MpService.c
|
||||
SyncTimer.c
|
||||
CpuS3.c
|
||||
CpuService.c
|
||||
CpuService.h
|
||||
SmmProfile.c
|
||||
SmmProfile.h
|
||||
SmmProfileInternal.h
|
||||
SmramSaveState.c
|
||||
SmmStm.c
|
||||
SmmStm.h
|
||||
|
||||
[Sources.Ia32]
|
||||
Ia32/Semaphore.c
|
||||
Ia32/PageTbl.c
|
||||
Ia32/SmmFuncsArch.c
|
||||
Ia32/SmmProfileArch.c
|
||||
Ia32/SmmProfileArch.h
|
||||
Ia32/SmmInit.asm | MSFT
|
||||
Ia32/SmiEntry.asm | MSFT
|
||||
Ia32/SmiException.asm | MSFT
|
||||
Ia32/MpFuncs.asm | MSFT
|
||||
|
||||
Ia32/SmmInit.asm | INTEL
|
||||
Ia32/SmiEntry.asm | INTEL
|
||||
Ia32/SmiException.asm | INTEL
|
||||
Ia32/MpFuncs.asm | INTEL
|
||||
|
||||
Ia32/SmmInit.S | GCC
|
||||
Ia32/SmiEntry.S | GCC
|
||||
Ia32/SmiException.S | GCC
|
||||
Ia32/MpFuncs.S | GCC
|
||||
|
||||
[Sources.X64]
|
||||
X64/Semaphore.c
|
||||
X64/PageTbl.c
|
||||
X64/SmmFuncsArch.c
|
||||
X64/SmmProfileArch.c
|
||||
X64/SmmProfileArch.h
|
||||
X64/SmmInit.asm | MSFT
|
||||
X64/SmiEntry.asm | MSFT
|
||||
X64/SmiException.asm | MSFT
|
||||
X64/MpFuncs.asm | MSFT
|
||||
|
||||
X64/SmmInit.asm | INTEL
|
||||
X64/SmiEntry.asm | INTEL
|
||||
X64/SmiException.asm | INTEL
|
||||
X64/MpFuncs.asm | INTEL
|
||||
|
||||
X64/SmmInit.S | GCC
|
||||
X64/SmiEntry.S | GCC
|
||||
X64/SmiException.S | GCC
|
||||
X64/MpFuncs.S | GCC
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
StmCpuPkg/StmCpuPkg.dec
|
||||
UefiCpuPkg/UefiCpuPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
UefiDriverEntryPoint
|
||||
UefiRuntimeServicesTableLib
|
||||
CacheMaintenanceLib
|
||||
PcdLib
|
||||
DebugLib
|
||||
BaseLib
|
||||
SynchronizationLib
|
||||
BaseMemoryLib
|
||||
MtrrLib
|
||||
IoLib
|
||||
TimerLib
|
||||
SmmServicesTableLib
|
||||
MemoryAllocationLib
|
||||
DebugAgentLib
|
||||
HobLib
|
||||
PciLib
|
||||
LocalApicLib
|
||||
UefiCpuLib
|
||||
SmmCpuPlatformHookLib
|
||||
CpuExceptionHandlerLib
|
||||
UefiLib
|
||||
DxeServicesTableLib
|
||||
CpuLib
|
||||
ReportStatusCodeLib
|
||||
SmmCpuFeaturesLib
|
||||
PeCoffGetEntryPointLib
|
||||
|
||||
[Protocols]
|
||||
gEfiSmmAccess2ProtocolGuid ## CONSUMES
|
||||
gEfiMpServiceProtocolGuid ## CONSUMES
|
||||
gEfiSmmConfigurationProtocolGuid ## PRODUCES
|
||||
gEfiSmmCpuProtocolGuid ## PRODUCES
|
||||
gEfiSmmReadyToLockProtocolGuid ## NOTIFY
|
||||
gEfiSmmEndOfDxeProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiSmmCpuServiceProtocolGuid ## PRODUCES
|
||||
gEfiSmMonitorInitProtocolGuid ## SOMETIMES_PRODUCES
|
||||
|
||||
[Guids]
|
||||
gEfiAcpiVariableGuid ## SOMETIMES_CONSUMES ## HOB # it is used for S3 boot.
|
||||
gEfiGlobalVariableGuid ## SOMETIMES_PRODUCES ## Variable:L"SmmProfileData"
|
||||
gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ## SystemTable
|
||||
gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ## SystemTable
|
||||
gMsegSmramGuid ## SOMETIMES_CONSUMES ## HOB
|
||||
|
||||
[FeaturePcd]
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug ## CONSUMES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp ## CONSUMES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection ## CONSUMES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport ## CONSUMES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard ## CONSUMES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable ## CONSUMES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer ## CONSUMES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock ## CONSUMES
|
||||
gStmCpuPkgTokenSpaceGuid.PcdCpuStmSupport ## CONSUMES
|
||||
|
||||
[Pcd]
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## SOMETIMES_CONSUMES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileSize ## SOMETIMES_CONSUMES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackSize ## CONSUMES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmApSyncTimeout ## CONSUMES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuS3DataAddress ## SOMETIMES_CONSUMES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugDataAddress ## SOMETIMES_PRODUCES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmCodeAccessCheckEnable ## CONSUMES
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmSyncMode ## CONSUMES
|
||||
gStmCpuPkgTokenSpaceGuid.PcdCpuMsegSize ## SOMETIMES_CONSUMES
|
||||
gStmCpuPkgTokenSpaceGuid.PcdCpuSmmStmExceptionStackSize ## SOMETIMES_CONSUMES
|
||||
|
||||
[Depex]
|
||||
gEfiMpServiceProtocolGuid
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
PiSmmCpuDxeSmmExtra.uni
|
|
@ -0,0 +1,21 @@
|
|||
// /** @file
|
||||
// CPU SMM driver.
|
||||
//
|
||||
// This SMM driver performs SMM initialization, deploy SMM Entry Vector,
|
||||
// provides CPU specific services in SMM.
|
||||
//
|
||||
// Copyright (c) 2009 - 2015, Intel Corporation. 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "CPU SMM driver"
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "This SMM driver performs SMM initialization, deploys SMM Entry Vector, and provides CPU-specific services in SMM."
|
|
@ -0,0 +1,18 @@
|
|||
// /** @file
|
||||
// PiSmmCpuDxeSmm Localized Strings and Content
|
||||
//
|
||||
// Copyright (c) 2013 - 2015, Intel Corporation. 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_PROPERTIES_MODULE_NAME
|
||||
#language en-US
|
||||
"Processor SMM Initialization DXE Driver"
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,138 @@
|
|||
/** @file
|
||||
SMM profile header file.
|
||||
|
||||
Copyright (c) 2012 - 2016, Intel Corporation. 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 _SMM_PROFILE_H_
|
||||
#define _SMM_PROFILE_H_
|
||||
|
||||
#include "SmmProfileInternal.h"
|
||||
|
||||
///
|
||||
/// MSR Register Index
|
||||
///
|
||||
#define MSR_IA32_MISC_ENABLE 0x1A0
|
||||
#define B_XD_DISABLE_BIT BIT34
|
||||
|
||||
//
|
||||
// External functions
|
||||
//
|
||||
|
||||
/**
|
||||
Initialize processor environment for SMM profile.
|
||||
|
||||
@param CpuIndex The index of the processor.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ActivateSmmProfile (
|
||||
IN UINTN CpuIndex
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize SMM profile in SMM CPU entry point.
|
||||
|
||||
@param[in] Cr3 The base address of the page tables to use in SMM.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitSmmProfile (
|
||||
UINT32 Cr3
|
||||
);
|
||||
|
||||
/**
|
||||
Increase SMI number in each SMI entry.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SmmProfileRecordSmiNum (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
The Page fault handler to save SMM profile data.
|
||||
|
||||
@param Rip The RIP when exception happens.
|
||||
@param ErrorCode The Error code of exception.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SmmProfilePFHandler (
|
||||
UINTN Rip,
|
||||
UINTN ErrorCode
|
||||
);
|
||||
|
||||
/**
|
||||
Updates page table to make some memory ranges (like system memory) absent
|
||||
and make some memory ranges (like MMIO) present and execute disable. It also
|
||||
update 2MB-page to 4KB-page for some memory ranges.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SmmProfileStart (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Page fault IDT handler for SMM Profile.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
PageFaultIdtHandlerSmmProfile (
|
||||
VOID
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Check if XD feature is supported by a processor.
|
||||
|
||||
@param[in,out] Buffer The pointer to private data buffer.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
CheckFeatureSupported (
|
||||
IN OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Enable XD feature.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ActivateXd (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Update page table according to protected memory ranges and the 4KB-page mapped memory ranges.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitPaging (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Check if XD and BTS features are supported by all processors.
|
||||
|
||||
**/
|
||||
VOID
|
||||
CheckProcessorFeature (
|
||||
VOID
|
||||
);
|
||||
|
||||
extern BOOLEAN mXdSupported;
|
||||
extern BOOLEAN mXdEnabled;
|
||||
|
||||
#endif // _SMM_PROFILE_H_
|
|
@ -0,0 +1,172 @@
|
|||
/** @file
|
||||
SMM profile internal header file.
|
||||
|
||||
Copyright (c) 2012 - 2015, Intel Corporation. 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 _SMM_PROFILE_INTERNAL_H_
|
||||
#define _SMM_PROFILE_INTERNAL_H_
|
||||
|
||||
#include <Guid/GlobalVariable.h>
|
||||
#include <Guid/Acpi.h>
|
||||
#include <Protocol/SmmReadyToLock.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/DxeServicesTableLib.h>
|
||||
#include <Library/CpuLib.h>
|
||||
#include <IndustryStandard/Acpi.h>
|
||||
|
||||
#include "SmmProfileArch.h"
|
||||
|
||||
//
|
||||
// Configure the SMM_PROFILE DTS region size
|
||||
//
|
||||
#define SMM_PROFILE_DTS_SIZE (4 * 1024 * 1024) // 4M
|
||||
|
||||
#define MAX_PF_PAGE_COUNT 0x2
|
||||
|
||||
#define PEBS_RECORD_NUMBER 0x2
|
||||
|
||||
#define MAX_PF_ENTRY_COUNT 10
|
||||
|
||||
//
|
||||
// This MACRO just enable unit test for the profile
|
||||
// Please disable it.
|
||||
//
|
||||
|
||||
#define IA32_PF_EC_P (1u << 0)
|
||||
#define IA32_PF_EC_WR (1u << 1)
|
||||
#define IA32_PF_EC_US (1u << 2)
|
||||
#define IA32_PF_EC_RSVD (1u << 3)
|
||||
#define IA32_PF_EC_ID (1u << 4)
|
||||
|
||||
#define SMM_PROFILE_NAME L"SmmProfileData"
|
||||
|
||||
//
|
||||
// CPU generic definition
|
||||
//
|
||||
#define CPUID1_EDX_XD_SUPPORT 0x100000
|
||||
#define MSR_EFER 0xc0000080
|
||||
#define MSR_EFER_XD 0x800
|
||||
|
||||
#define CPUID1_EDX_BTS_AVAILABLE 0x200000
|
||||
|
||||
#define DR6_SINGLE_STEP 0x4000
|
||||
#define RFLAG_TF 0x100
|
||||
|
||||
#define MSR_DEBUG_CTL 0x1D9
|
||||
#define MSR_DEBUG_CTL_LBR 0x1
|
||||
#define MSR_DEBUG_CTL_TR 0x40
|
||||
#define MSR_DEBUG_CTL_BTS 0x80
|
||||
#define MSR_DEBUG_CTL_BTINT 0x100
|
||||
#define MSR_LASTBRANCH_TOS 0x1C9
|
||||
#define MSR_LER_FROM_LIP 0x1DD
|
||||
#define MSR_LER_TO_LIP 0x1DE
|
||||
#define MSR_DS_AREA 0x600
|
||||
|
||||
typedef struct {
|
||||
EFI_PHYSICAL_ADDRESS Base;
|
||||
EFI_PHYSICAL_ADDRESS Top;
|
||||
} MEMORY_RANGE;
|
||||
|
||||
typedef struct {
|
||||
MEMORY_RANGE Range;
|
||||
BOOLEAN Present;
|
||||
BOOLEAN Nx;
|
||||
} MEMORY_PROTECTION_RANGE;
|
||||
|
||||
typedef struct {
|
||||
UINT64 HeaderSize;
|
||||
UINT64 MaxDataEntries;
|
||||
UINT64 MaxDataSize;
|
||||
UINT64 CurDataEntries;
|
||||
UINT64 CurDataSize;
|
||||
UINT64 TsegStart;
|
||||
UINT64 TsegSize;
|
||||
UINT64 NumSmis;
|
||||
UINT64 NumCpus;
|
||||
} SMM_PROFILE_HEADER;
|
||||
|
||||
typedef struct {
|
||||
UINT64 SmiNum;
|
||||
UINT64 CpuNum;
|
||||
UINT64 ApicId;
|
||||
UINT64 ErrorCode;
|
||||
UINT64 Instruction;
|
||||
UINT64 Address;
|
||||
UINT64 SmiCmd;
|
||||
} SMM_PROFILE_ENTRY;
|
||||
|
||||
extern SMM_S3_RESUME_STATE *mSmmS3ResumeState;
|
||||
extern UINTN gSmiExceptionHandlers[];
|
||||
extern BOOLEAN mXdSupported;
|
||||
extern UINTN *mPFEntryCount;
|
||||
extern UINT64 (*mLastPFEntryValue)[MAX_PF_ENTRY_COUNT];
|
||||
extern UINT64 *(*mLastPFEntryPointer)[MAX_PF_ENTRY_COUNT];
|
||||
|
||||
//
|
||||
// Internal functions
|
||||
//
|
||||
|
||||
/**
|
||||
Update IDT table to replace page fault handler and INT 1 handler.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitIdtr (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Check if the memory address will be mapped by 4KB-page.
|
||||
|
||||
@param Address The address of Memory.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsAddressSplit (
|
||||
IN EFI_PHYSICAL_ADDRESS Address
|
||||
);
|
||||
|
||||
/**
|
||||
Check if the memory address will be mapped by 4KB-page.
|
||||
|
||||
@param Address The address of Memory.
|
||||
@param Nx The flag indicates if the memory is execute-disable.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsAddressValid (
|
||||
IN EFI_PHYSICAL_ADDRESS Address,
|
||||
IN BOOLEAN *Nx
|
||||
);
|
||||
|
||||
/**
|
||||
Page Fault handler for SMM use.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SmiDefaultPFHandler (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Clear TF in FLAGS.
|
||||
|
||||
@param SystemContext A pointer to the processor context when
|
||||
the interrupt occurred on the processor.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ClearTrapFlag (
|
||||
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
||||
);
|
||||
|
||||
#endif // _SMM_PROFILE_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,146 @@
|
|||
/** @file
|
||||
SMM STM support
|
||||
|
||||
Copyright (c) 2015 - 2016, Intel Corporation. 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 _SMM_STM_H_
|
||||
#define _SMM_STM_H_
|
||||
|
||||
#include <Protocol/SmMonitorInit.h>
|
||||
|
||||
#define IA32_VMX_BASIC_MSR_INDEX 0x480
|
||||
#define IA32_VMX_MISC_MSR_INDEX 0x485
|
||||
#define IA32_SMM_MONITOR_CTL_MSR_INDEX 0x9B
|
||||
#define IA32_SMM_MONITOR_VALID BIT0
|
||||
|
||||
/**
|
||||
|
||||
Get STM state.
|
||||
|
||||
@return STM state
|
||||
|
||||
**/
|
||||
EFI_SM_MONITOR_STATE
|
||||
EFIAPI
|
||||
GetMonitorState (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
Load STM image to MSEG.
|
||||
|
||||
@param StmImage STM image
|
||||
@param StmImageSize STM image size
|
||||
|
||||
@retval EFI_SUCCESS Load STM to MSEG successfully
|
||||
@retval EFI_BUFFER_TOO_SMALL MSEG is smaller than minimal requirement of STM image
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
LoadMonitor (
|
||||
IN EFI_PHYSICAL_ADDRESS StmImage,
|
||||
IN UINTN StmImageSize
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
Add resources in list to database. Allocate new memory areas as needed.
|
||||
|
||||
@param ResourceList A pointer to resource list to be added
|
||||
@param NumEntries Optional number of entries.
|
||||
If 0, list must be terminated by END_OF_RESOURCES.
|
||||
|
||||
@retval EFI_SUCCESS If resources are added
|
||||
@retval EFI_INVALID_PARAMETER If nested procedure detected resource failer
|
||||
@retval EFI_OUT_OF_RESOURCES If nested procedure returned it and we cannot allocate more areas.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
AddPiResource (
|
||||
IN STM_RSC *ResourceList,
|
||||
IN UINT32 NumEntries OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
Delete resources in list to database.
|
||||
|
||||
@param ResourceList A pointer to resource list to be deleted
|
||||
NULL means delete all resources.
|
||||
@param NumEntries Optional number of entries.
|
||||
If 0, list must be terminated by END_OF_RESOURCES.
|
||||
|
||||
@retval EFI_SUCCESS If resources are deleted
|
||||
@retval EFI_INVALID_PARAMETER If nested procedure detected resource failer
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DeletePiResource (
|
||||
IN STM_RSC *ResourceList,
|
||||
IN UINT32 NumEntries OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
Get BIOS resources.
|
||||
|
||||
@param ResourceList A pointer to resource list to be filled
|
||||
@param ResourceSize On input it means size of resource list input.
|
||||
On output it means size of resource list filled,
|
||||
or the size of resource list to be filled if size of too small.
|
||||
|
||||
@retval EFI_SUCCESS If resources are returned.
|
||||
@retval EFI_BUFFER_TOO_SMALL If resource list buffer is too small to hold the whole resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetPiResource (
|
||||
OUT STM_RSC *ResourceList,
|
||||
IN OUT UINT32 *ResourceSize
|
||||
);
|
||||
|
||||
/**
|
||||
This functin initialize STM configuration table.
|
||||
**/
|
||||
VOID
|
||||
StmSmmConfigurationTableInit (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
This function notify STM resource change.
|
||||
|
||||
@param StmResource BIOS STM resource
|
||||
|
||||
**/
|
||||
VOID
|
||||
NotifyStmResourceChange (
|
||||
IN VOID *StmResource
|
||||
);
|
||||
|
||||
/**
|
||||
This function return BIOS STM resource.
|
||||
|
||||
@return BIOS STM resource
|
||||
|
||||
**/
|
||||
VOID *
|
||||
GetStmResource (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,722 @@
|
|||
/** @file
|
||||
Provides services to access SMRAM Save State Map
|
||||
|
||||
Copyright (c) 2010 - 2016, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include <PiSmm.h>
|
||||
|
||||
#include <Library/SmmCpuFeaturesLib.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/SmmServicesTableLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Register/Cpuid.h>
|
||||
#include <Register/SmramSaveStateMap.h>
|
||||
|
||||
//
|
||||
// EFER register LMA bit
|
||||
//
|
||||
#define LMA BIT10
|
||||
|
||||
///
|
||||
/// Macro used to simplify the lookup table entries of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
|
||||
///
|
||||
#define SMM_CPU_OFFSET(Field) OFFSET_OF (SMRAM_SAVE_STATE_MAP, Field)
|
||||
|
||||
///
|
||||
/// Macro used to simplify the lookup table entries of type CPU_SMM_SAVE_STATE_REGISTER_RANGE
|
||||
///
|
||||
#define SMM_REGISTER_RANGE(Start, End) { Start, End, End - Start + 1 }
|
||||
|
||||
///
|
||||
/// Structure used to describe a range of registers
|
||||
///
|
||||
typedef struct {
|
||||
EFI_SMM_SAVE_STATE_REGISTER Start;
|
||||
EFI_SMM_SAVE_STATE_REGISTER End;
|
||||
UINTN Length;
|
||||
} CPU_SMM_SAVE_STATE_REGISTER_RANGE;
|
||||
|
||||
///
|
||||
/// Structure used to build a lookup table to retrieve the widths and offsets
|
||||
/// associated with each supported EFI_SMM_SAVE_STATE_REGISTER value
|
||||
///
|
||||
|
||||
#define SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX 1
|
||||
#define SMM_SAVE_STATE_REGISTER_IOMISC_INDEX 2
|
||||
#define SMM_SAVE_STATE_REGISTER_IOMEMADDR_INDEX 3
|
||||
#define SMM_SAVE_STATE_REGISTER_MAX_INDEX 4
|
||||
|
||||
typedef struct {
|
||||
UINT8 Width32;
|
||||
UINT8 Width64;
|
||||
UINT16 Offset32;
|
||||
UINT16 Offset64Lo;
|
||||
UINT16 Offset64Hi;
|
||||
BOOLEAN Writeable;
|
||||
} CPU_SMM_SAVE_STATE_LOOKUP_ENTRY;
|
||||
|
||||
///
|
||||
/// Structure used to build a lookup table for the IOMisc width information
|
||||
///
|
||||
typedef struct {
|
||||
UINT8 Width;
|
||||
EFI_SMM_SAVE_STATE_IO_WIDTH IoWidth;
|
||||
} CPU_SMM_SAVE_STATE_IO_WIDTH;
|
||||
|
||||
///
|
||||
/// Variables from SMI Handler
|
||||
///
|
||||
extern UINT32 gSmbase;
|
||||
extern volatile UINT32 gSmiStack;
|
||||
extern UINT32 gSmiCr3;
|
||||
extern volatile UINT8 gcSmiHandlerTemplate[];
|
||||
extern CONST UINT16 gcSmiHandlerSize;
|
||||
extern CONST UINT16 gcSmiHandlerOffset;
|
||||
|
||||
//
|
||||
// Variables used by SMI Handler
|
||||
//
|
||||
IA32_DESCRIPTOR gSmiHandlerIdtr;
|
||||
|
||||
///
|
||||
/// Table used by GetRegisterIndex() to convert an EFI_SMM_SAVE_STATE_REGISTER
|
||||
/// value to an index into a table of type CPU_SMM_SAVE_STATE_LOOKUP_ENTRY
|
||||
///
|
||||
CONST CPU_SMM_SAVE_STATE_REGISTER_RANGE mSmmCpuRegisterRanges[] = {
|
||||
SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_GDTBASE, EFI_SMM_SAVE_STATE_REGISTER_LDTINFO),
|
||||
SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_ES, EFI_SMM_SAVE_STATE_REGISTER_RIP),
|
||||
SMM_REGISTER_RANGE (EFI_SMM_SAVE_STATE_REGISTER_RFLAGS, EFI_SMM_SAVE_STATE_REGISTER_CR4),
|
||||
{ (EFI_SMM_SAVE_STATE_REGISTER)0, (EFI_SMM_SAVE_STATE_REGISTER)0, 0 }
|
||||
};
|
||||
|
||||
///
|
||||
/// Lookup table used to retrieve the widths and offsets associated with each
|
||||
/// supported EFI_SMM_SAVE_STATE_REGISTER value
|
||||
///
|
||||
CONST CPU_SMM_SAVE_STATE_LOOKUP_ENTRY mSmmCpuWidthOffset[] = {
|
||||
{0, 0, 0, 0, 0, FALSE}, // Reserved
|
||||
|
||||
//
|
||||
// Internally defined CPU Save State Registers. Not defined in PI SMM CPU Protocol.
|
||||
//
|
||||
{4, 4, SMM_CPU_OFFSET (x86.SMMRevId) , SMM_CPU_OFFSET (x64.SMMRevId) , 0 , FALSE}, // SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX = 1
|
||||
{4, 4, SMM_CPU_OFFSET (x86.IOMisc) , SMM_CPU_OFFSET (x64.IOMisc) , 0 , FALSE}, // SMM_SAVE_STATE_REGISTER_IOMISC_INDEX = 2
|
||||
{4, 8, SMM_CPU_OFFSET (x86.IOMemAddr) , SMM_CPU_OFFSET (x64.IOMemAddr) , SMM_CPU_OFFSET (x64.IOMemAddr) + 4, FALSE}, // SMM_SAVE_STATE_REGISTER_IOMEMADDR_INDEX = 3
|
||||
|
||||
//
|
||||
// CPU Save State registers defined in PI SMM CPU Protocol.
|
||||
//
|
||||
{0, 8, 0 , SMM_CPU_OFFSET (x64.GdtBaseLoDword) , SMM_CPU_OFFSET (x64.GdtBaseHiDword), FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_GDTBASE = 4
|
||||
{0, 8, 0 , SMM_CPU_OFFSET (x64.IdtBaseLoDword) , SMM_CPU_OFFSET (x64.IdtBaseHiDword), FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_IDTBASE = 5
|
||||
{0, 8, 0 , SMM_CPU_OFFSET (x64.LdtBaseLoDword) , SMM_CPU_OFFSET (x64.LdtBaseHiDword), FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_LDTBASE = 6
|
||||
{0, 0, 0 , 0 , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_GDTLIMIT = 7
|
||||
{0, 0, 0 , 0 , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_IDTLIMIT = 8
|
||||
{0, 0, 0 , 0 , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_LDTLIMIT = 9
|
||||
{0, 0, 0 , 0 , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_LDTINFO = 10
|
||||
|
||||
{4, 4, SMM_CPU_OFFSET (x86._ES) , SMM_CPU_OFFSET (x64._ES) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_ES = 20
|
||||
{4, 4, SMM_CPU_OFFSET (x86._CS) , SMM_CPU_OFFSET (x64._CS) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_CS = 21
|
||||
{4, 4, SMM_CPU_OFFSET (x86._SS) , SMM_CPU_OFFSET (x64._SS) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_SS = 22
|
||||
{4, 4, SMM_CPU_OFFSET (x86._DS) , SMM_CPU_OFFSET (x64._DS) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_DS = 23
|
||||
{4, 4, SMM_CPU_OFFSET (x86._FS) , SMM_CPU_OFFSET (x64._FS) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_FS = 24
|
||||
{4, 4, SMM_CPU_OFFSET (x86._GS) , SMM_CPU_OFFSET (x64._GS) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_GS = 25
|
||||
{0, 4, 0 , SMM_CPU_OFFSET (x64._LDTR) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_LDTR_SEL = 26
|
||||
{4, 4, SMM_CPU_OFFSET (x86._TR) , SMM_CPU_OFFSET (x64._TR) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_TR_SEL = 27
|
||||
{4, 8, SMM_CPU_OFFSET (x86._DR7) , SMM_CPU_OFFSET (x64._DR7) , SMM_CPU_OFFSET (x64._DR7) + 4, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_DR7 = 28
|
||||
{4, 8, SMM_CPU_OFFSET (x86._DR6) , SMM_CPU_OFFSET (x64._DR6) , SMM_CPU_OFFSET (x64._DR6) + 4, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_DR6 = 29
|
||||
{0, 8, 0 , SMM_CPU_OFFSET (x64._R8) , SMM_CPU_OFFSET (x64._R8) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R8 = 30
|
||||
{0, 8, 0 , SMM_CPU_OFFSET (x64._R9) , SMM_CPU_OFFSET (x64._R9) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R9 = 31
|
||||
{0, 8, 0 , SMM_CPU_OFFSET (x64._R10) , SMM_CPU_OFFSET (x64._R10) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R10 = 32
|
||||
{0, 8, 0 , SMM_CPU_OFFSET (x64._R11) , SMM_CPU_OFFSET (x64._R11) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R11 = 33
|
||||
{0, 8, 0 , SMM_CPU_OFFSET (x64._R12) , SMM_CPU_OFFSET (x64._R12) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R12 = 34
|
||||
{0, 8, 0 , SMM_CPU_OFFSET (x64._R13) , SMM_CPU_OFFSET (x64._R13) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R13 = 35
|
||||
{0, 8, 0 , SMM_CPU_OFFSET (x64._R14) , SMM_CPU_OFFSET (x64._R14) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R14 = 36
|
||||
{0, 8, 0 , SMM_CPU_OFFSET (x64._R15) , SMM_CPU_OFFSET (x64._R15) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_R15 = 37
|
||||
{4, 8, SMM_CPU_OFFSET (x86._EAX) , SMM_CPU_OFFSET (x64._RAX) , SMM_CPU_OFFSET (x64._RAX) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RAX = 38
|
||||
{4, 8, SMM_CPU_OFFSET (x86._EBX) , SMM_CPU_OFFSET (x64._RBX) , SMM_CPU_OFFSET (x64._RBX) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RBX = 39
|
||||
{4, 8, SMM_CPU_OFFSET (x86._ECX) , SMM_CPU_OFFSET (x64._RCX) , SMM_CPU_OFFSET (x64._RCX) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RCX = 40
|
||||
{4, 8, SMM_CPU_OFFSET (x86._EDX) , SMM_CPU_OFFSET (x64._RDX) , SMM_CPU_OFFSET (x64._RDX) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RDX = 41
|
||||
{4, 8, SMM_CPU_OFFSET (x86._ESP) , SMM_CPU_OFFSET (x64._RSP) , SMM_CPU_OFFSET (x64._RSP) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RSP = 42
|
||||
{4, 8, SMM_CPU_OFFSET (x86._EBP) , SMM_CPU_OFFSET (x64._RBP) , SMM_CPU_OFFSET (x64._RBP) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RBP = 43
|
||||
{4, 8, SMM_CPU_OFFSET (x86._ESI) , SMM_CPU_OFFSET (x64._RSI) , SMM_CPU_OFFSET (x64._RSI) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RSI = 44
|
||||
{4, 8, SMM_CPU_OFFSET (x86._EDI) , SMM_CPU_OFFSET (x64._RDI) , SMM_CPU_OFFSET (x64._RDI) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RDI = 45
|
||||
{4, 8, SMM_CPU_OFFSET (x86._EIP) , SMM_CPU_OFFSET (x64._RIP) , SMM_CPU_OFFSET (x64._RIP) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RIP = 46
|
||||
|
||||
{4, 8, SMM_CPU_OFFSET (x86._EFLAGS) , SMM_CPU_OFFSET (x64._RFLAGS) , SMM_CPU_OFFSET (x64._RFLAGS) + 4, TRUE }, // EFI_SMM_SAVE_STATE_REGISTER_RFLAGS = 51
|
||||
{4, 8, SMM_CPU_OFFSET (x86._CR0) , SMM_CPU_OFFSET (x64._CR0) , SMM_CPU_OFFSET (x64._CR0) + 4, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_CR0 = 52
|
||||
{4, 8, SMM_CPU_OFFSET (x86._CR3) , SMM_CPU_OFFSET (x64._CR3) , SMM_CPU_OFFSET (x64._CR3) + 4, FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_CR3 = 53
|
||||
{0, 4, 0 , SMM_CPU_OFFSET (x64._CR4) , 0 , FALSE}, // EFI_SMM_SAVE_STATE_REGISTER_CR4 = 54
|
||||
};
|
||||
|
||||
///
|
||||
/// Lookup table for the IOMisc width information
|
||||
///
|
||||
CONST CPU_SMM_SAVE_STATE_IO_WIDTH mSmmCpuIoWidth[] = {
|
||||
{ 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 0
|
||||
{ 1, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // SMM_IO_LENGTH_BYTE = 1
|
||||
{ 2, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT16 }, // SMM_IO_LENGTH_WORD = 2
|
||||
{ 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 3
|
||||
{ 4, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT32 }, // SMM_IO_LENGTH_DWORD = 4
|
||||
{ 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 5
|
||||
{ 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 }, // Undefined = 6
|
||||
{ 0, EFI_SMM_SAVE_STATE_IO_WIDTH_UINT8 } // Undefined = 7
|
||||
};
|
||||
|
||||
///
|
||||
/// Lookup table for the IOMisc type information
|
||||
///
|
||||
CONST EFI_SMM_SAVE_STATE_IO_TYPE mSmmCpuIoType[] = {
|
||||
EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT, // SMM_IO_TYPE_OUT_DX = 0
|
||||
EFI_SMM_SAVE_STATE_IO_TYPE_INPUT, // SMM_IO_TYPE_IN_DX = 1
|
||||
EFI_SMM_SAVE_STATE_IO_TYPE_STRING, // SMM_IO_TYPE_OUTS = 2
|
||||
EFI_SMM_SAVE_STATE_IO_TYPE_STRING, // SMM_IO_TYPE_INS = 3
|
||||
(EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 4
|
||||
(EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 5
|
||||
EFI_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX, // SMM_IO_TYPE_REP_OUTS = 6
|
||||
EFI_SMM_SAVE_STATE_IO_TYPE_REP_PREFIX, // SMM_IO_TYPE_REP_INS = 7
|
||||
EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT, // SMM_IO_TYPE_OUT_IMMEDIATE = 8
|
||||
EFI_SMM_SAVE_STATE_IO_TYPE_INPUT, // SMM_IO_TYPE_OUT_IMMEDIATE = 9
|
||||
(EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 10
|
||||
(EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 11
|
||||
(EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 12
|
||||
(EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 13
|
||||
(EFI_SMM_SAVE_STATE_IO_TYPE)0, // Undefined = 14
|
||||
(EFI_SMM_SAVE_STATE_IO_TYPE)0 // Undefined = 15
|
||||
};
|
||||
|
||||
///
|
||||
/// The mode of the CPU at the time an SMI occurs
|
||||
///
|
||||
UINT8 mSmmSaveStateRegisterLma;
|
||||
|
||||
/**
|
||||
Read information from the CPU save state.
|
||||
|
||||
@param Register Specifies the CPU register to read form the save state.
|
||||
|
||||
@retval 0 Register is not valid
|
||||
@retval >0 Index into mSmmCpuWidthOffset[] associated with Register
|
||||
|
||||
**/
|
||||
UINTN
|
||||
GetRegisterIndex (
|
||||
IN EFI_SMM_SAVE_STATE_REGISTER Register
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINTN Offset;
|
||||
|
||||
for (Index = 0, Offset = SMM_SAVE_STATE_REGISTER_MAX_INDEX; mSmmCpuRegisterRanges[Index].Length != 0; Index++) {
|
||||
if (Register >= mSmmCpuRegisterRanges[Index].Start && Register <= mSmmCpuRegisterRanges[Index].End) {
|
||||
return Register - mSmmCpuRegisterRanges[Index].Start + Offset;
|
||||
}
|
||||
Offset += mSmmCpuRegisterRanges[Index].Length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
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
|
||||
ReadSaveStateRegisterByIndex (
|
||||
IN UINTN CpuIndex,
|
||||
IN UINTN RegisterIndex,
|
||||
IN UINTN Width,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
SMRAM_SAVE_STATE_MAP *CpuSaveState;
|
||||
|
||||
if (RegisterIndex == 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
CpuSaveState = gSmst->CpuSaveState[CpuIndex];
|
||||
|
||||
if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
|
||||
//
|
||||
// If 32-bit mode width is zero, then the specified register can not be accessed
|
||||
//
|
||||
if (mSmmCpuWidthOffset[RegisterIndex].Width32 == 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// If Width is bigger than the 32-bit mode width, then the specified register can not be accessed
|
||||
//
|
||||
if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Write return buffer
|
||||
//
|
||||
ASSERT(CpuSaveState != NULL);
|
||||
CopyMem(Buffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset32, Width);
|
||||
} else {
|
||||
//
|
||||
// If 64-bit mode width is zero, then the specified register can not be accessed
|
||||
//
|
||||
if (mSmmCpuWidthOffset[RegisterIndex].Width64 == 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// If Width is bigger than the 64-bit mode width, then the specified register can not be accessed
|
||||
//
|
||||
if (Width > mSmmCpuWidthOffset[RegisterIndex].Width64) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Write lower 32-bits of return buffer
|
||||
//
|
||||
CopyMem(Buffer, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Lo, MIN(4, Width));
|
||||
if (Width >= 4) {
|
||||
//
|
||||
// Write upper 32-bits of return buffer
|
||||
//
|
||||
CopyMem((UINT8 *)Buffer + 4, (UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, Width - 4);
|
||||
}
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
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
|
||||
)
|
||||
{
|
||||
UINT32 SmmRevId;
|
||||
SMRAM_SAVE_STATE_IOMISC IoMisc;
|
||||
EFI_SMM_SAVE_STATE_IO_INFO *IoInfo;
|
||||
VOID *IoMemAddr;
|
||||
|
||||
//
|
||||
// Check for special EFI_SMM_SAVE_STATE_REGISTER_LMA
|
||||
//
|
||||
if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) {
|
||||
//
|
||||
// Only byte access is supported for this register
|
||||
//
|
||||
if (Width != 1) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*(UINT8 *)Buffer = mSmmSaveStateRegisterLma;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Check for special EFI_SMM_SAVE_STATE_REGISTER_IO
|
||||
//
|
||||
if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) {
|
||||
//
|
||||
// Get SMM Revision ID
|
||||
//
|
||||
ReadSaveStateRegisterByIndex (CpuIndex, SMM_SAVE_STATE_REGISTER_SMMREVID_INDEX, sizeof(SmmRevId), &SmmRevId);
|
||||
|
||||
//
|
||||
// See if the CPU supports the IOMisc register in the save state
|
||||
//
|
||||
if (SmmRevId < SMRAM_SAVE_STATE_MIN_REV_ID_IOMISC) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the IOMisc register value
|
||||
//
|
||||
ReadSaveStateRegisterByIndex (CpuIndex, SMM_SAVE_STATE_REGISTER_IOMISC_INDEX, sizeof(IoMisc.Uint32), &IoMisc.Uint32);
|
||||
|
||||
//
|
||||
// Check for the SMI_FLAG in IOMisc
|
||||
//
|
||||
if (IoMisc.Bits.SmiFlag == 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// Compute index for the I/O Length and I/O Type lookup tables
|
||||
//
|
||||
if (mSmmCpuIoWidth[IoMisc.Bits.Length].Width == 0 || mSmmCpuIoType[IoMisc.Bits.Type] == 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// Zero the IoInfo structure that will be returned in Buffer
|
||||
//
|
||||
IoInfo = (EFI_SMM_SAVE_STATE_IO_INFO *)Buffer;
|
||||
ZeroMem (IoInfo, sizeof(EFI_SMM_SAVE_STATE_IO_INFO));
|
||||
|
||||
//
|
||||
// Use lookup tables to help fill in all the fields of the IoInfo structure
|
||||
//
|
||||
IoInfo->IoPort = (UINT16)IoMisc.Bits.Port;
|
||||
IoInfo->IoWidth = mSmmCpuIoWidth[IoMisc.Bits.Length].IoWidth;
|
||||
IoInfo->IoType = mSmmCpuIoType[IoMisc.Bits.Type];
|
||||
if (IoInfo->IoType == EFI_SMM_SAVE_STATE_IO_TYPE_INPUT || IoInfo->IoType == EFI_SMM_SAVE_STATE_IO_TYPE_OUTPUT) {
|
||||
ReadSaveStateRegister (CpuIndex, EFI_SMM_SAVE_STATE_REGISTER_RAX, mSmmCpuIoWidth[IoMisc.Bits.Length].Width, &IoInfo->IoData);
|
||||
}
|
||||
else {
|
||||
ReadSaveStateRegisterByIndex(CpuIndex, SMM_SAVE_STATE_REGISTER_IOMEMADDR_INDEX, sizeof(IoMemAddr), &IoMemAddr);
|
||||
CopyMem(&IoInfo->IoData, IoMemAddr, mSmmCpuIoWidth[IoMisc.Bits.Length].Width);
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Convert Register to a register lookup table index
|
||||
//
|
||||
return ReadSaveStateRegisterByIndex (CpuIndex, GetRegisterIndex (Register), Width, 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
|
||||
)
|
||||
{
|
||||
UINTN RegisterIndex;
|
||||
SMRAM_SAVE_STATE_MAP *CpuSaveState;
|
||||
|
||||
//
|
||||
// Writes to EFI_SMM_SAVE_STATE_REGISTER_LMA are ignored
|
||||
//
|
||||
if (Register == EFI_SMM_SAVE_STATE_REGISTER_LMA) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Writes to EFI_SMM_SAVE_STATE_REGISTER_IO are not supported
|
||||
//
|
||||
if (Register == EFI_SMM_SAVE_STATE_REGISTER_IO) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// Convert Register to a register lookup table index
|
||||
//
|
||||
RegisterIndex = GetRegisterIndex (Register);
|
||||
if (RegisterIndex == 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
CpuSaveState = gSmst->CpuSaveState[CpuIndex];
|
||||
|
||||
//
|
||||
// Do not write non-writable SaveState, because it will cause exception.
|
||||
//
|
||||
if (!mSmmCpuWidthOffset[RegisterIndex].Writeable) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Check CPU mode
|
||||
//
|
||||
if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
|
||||
//
|
||||
// If 32-bit mode width is zero, then the specified register can not be accessed
|
||||
//
|
||||
if (mSmmCpuWidthOffset[RegisterIndex].Width32 == 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// If Width is bigger than the 32-bit mode width, then the specified register can not be accessed
|
||||
//
|
||||
if (Width > mSmmCpuWidthOffset[RegisterIndex].Width32) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
//
|
||||
// Write SMM State register
|
||||
//
|
||||
ASSERT (CpuSaveState != NULL);
|
||||
CopyMem((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset32, Buffer, Width);
|
||||
} else {
|
||||
//
|
||||
// If 64-bit mode width is zero, then the specified register can not be accessed
|
||||
//
|
||||
if (mSmmCpuWidthOffset[RegisterIndex].Width64 == 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// If Width is bigger than the 64-bit mode width, then the specified register can not be accessed
|
||||
//
|
||||
if (Width > mSmmCpuWidthOffset[RegisterIndex].Width64) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Write lower 32-bits of SMM State register
|
||||
//
|
||||
CopyMem((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Lo, Buffer, MIN (4, Width));
|
||||
if (Width >= 4) {
|
||||
//
|
||||
// Write upper 32-bits of SMM State register
|
||||
//
|
||||
CopyMem((UINT8 *)CpuSaveState + mSmmCpuWidthOffset[RegisterIndex].Offset64Hi, (UINT8 *)Buffer + 4, Width - 4);
|
||||
}
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
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
|
||||
)
|
||||
{
|
||||
UINT64 OriginalInstructionPointer;
|
||||
|
||||
OriginalInstructionPointer = SmmCpuFeaturesHookReturnFromSmm (
|
||||
CpuIndex,
|
||||
CpuState,
|
||||
NewInstructionPointer32,
|
||||
NewInstructionPointer
|
||||
);
|
||||
if (OriginalInstructionPointer != 0) {
|
||||
return OriginalInstructionPointer;
|
||||
}
|
||||
|
||||
if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
|
||||
OriginalInstructionPointer = (UINT64)CpuState->x86._EIP;
|
||||
CpuState->x86._EIP = (UINT32)NewInstructionPointer;
|
||||
//
|
||||
// Clear the auto HALT restart flag so the RSM instruction returns
|
||||
// program control to the instruction following the HLT instruction.
|
||||
//
|
||||
if ((CpuState->x86.AutoHALTRestart & BIT0) != 0) {
|
||||
CpuState->x86.AutoHALTRestart &= ~BIT0;
|
||||
}
|
||||
} else {
|
||||
OriginalInstructionPointer = CpuState->x64._RIP;
|
||||
if ((CpuState->x64.IA32_EFER & LMA) == 0) {
|
||||
CpuState->x64._RIP = (UINT32)NewInstructionPointer32;
|
||||
} else {
|
||||
CpuState->x64._RIP = (UINT32)NewInstructionPointer;
|
||||
}
|
||||
//
|
||||
// Clear the auto HALT restart flag so the RSM instruction returns
|
||||
// program control to the instruction following the HLT instruction.
|
||||
//
|
||||
if ((CpuState->x64.AutoHALTRestart & BIT0) != 0) {
|
||||
CpuState->x64.AutoHALTRestart &= ~BIT0;
|
||||
}
|
||||
}
|
||||
return OriginalInstructionPointer;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the size of the SMI Handler in bytes.
|
||||
|
||||
@retval The size, in bytes, of the SMI Handler.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
GetSmiHandlerSize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN Size;
|
||||
|
||||
Size = SmmCpuFeaturesGetSmiHandlerSize ();
|
||||
if (Size != 0) {
|
||||
return Size;
|
||||
}
|
||||
return gcSmiHandlerSize;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the offset of the native SMI Handler.
|
||||
|
||||
@retval The offset of the native SMI Handler.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
GetSmiHandlerOffset (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN Offset;
|
||||
|
||||
Offset = SmmCpuFeaturesGetSmiHandlerOffset ();
|
||||
if (Offset != 0) {
|
||||
return Offset;
|
||||
}
|
||||
return gcSmiHandlerOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
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
|
||||
)
|
||||
{
|
||||
if (SmmCpuFeaturesGetSmiHandlerSize () != 0) {
|
||||
//
|
||||
// Install SMI handler provided by library
|
||||
//
|
||||
SmmCpuFeaturesInstallSmiHandler (
|
||||
CpuIndex,
|
||||
SmBase,
|
||||
SmiStack,
|
||||
StackSize,
|
||||
GdtBase,
|
||||
GdtSize,
|
||||
IdtBase,
|
||||
IdtSize,
|
||||
Cr3
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize values in template before copy
|
||||
//
|
||||
gSmiStack = (UINT32)((UINTN)SmiStack + StackSize - sizeof (UINTN));
|
||||
gSmiCr3 = Cr3;
|
||||
gSmbase = SmBase;
|
||||
gSmiHandlerIdtr.Base = IdtBase;
|
||||
gSmiHandlerIdtr.Limit = (UINT16)(IdtSize - 1);
|
||||
|
||||
//
|
||||
// Set the value at the top of the CPU stack to the CPU Index
|
||||
//
|
||||
*(UINTN*)(UINTN)gSmiStack = CpuIndex;
|
||||
|
||||
//
|
||||
// Copy template to CPU specific SMI handler location
|
||||
//
|
||||
CopyMem (
|
||||
(VOID*)(UINTN)(SmBase + SMM_HANDLER_OFFSET),
|
||||
(VOID*)gcSmiHandlerTemplate,
|
||||
gcSmiHandlerSize
|
||||
);
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/** @file
|
||||
SMM Timer feature support
|
||||
|
||||
Copyright (c) 2009 - 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "PiSmmCpuDxeSmm.h"
|
||||
|
||||
UINT64 mTimeoutTicker = 0;
|
||||
//
|
||||
// Number of counts in a roll-over cycle of the performance counter.
|
||||
//
|
||||
UINT64 mCycle = 0;
|
||||
//
|
||||
// Flag to indicate the performance counter is count-up or count-down.
|
||||
//
|
||||
BOOLEAN mCountDown;
|
||||
|
||||
/**
|
||||
Initialize Timer for SMM AP Sync.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitializeSmmTimer (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT64 TimerFrequency;
|
||||
UINT64 Start;
|
||||
UINT64 End;
|
||||
|
||||
TimerFrequency = GetPerformanceCounterProperties (&Start, &End);
|
||||
mTimeoutTicker = DivU64x32 (
|
||||
MultU64x64(TimerFrequency, PcdGet64 (PcdCpuSmmApSyncTimeout)),
|
||||
1000 * 1000
|
||||
);
|
||||
if (End < Start) {
|
||||
mCountDown = TRUE;
|
||||
mCycle = Start - End;
|
||||
} else {
|
||||
mCountDown = FALSE;
|
||||
mCycle = End - Start;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Start Timer for SMM AP Sync.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
StartSyncTimer (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return GetPerformanceCounter ();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check if the SMM AP Sync timer is timeout.
|
||||
|
||||
@param Timer The start timer from the begin.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
IsSyncTimerTimeout (
|
||||
IN UINT64 Timer
|
||||
)
|
||||
{
|
||||
UINT64 CurrentTimer;
|
||||
UINT64 Delta;
|
||||
|
||||
CurrentTimer = GetPerformanceCounter ();
|
||||
//
|
||||
// We need to consider the case that CurrentTimer is equal to Timer
|
||||
// when some timer runs too slow and CPU runs fast. We think roll over
|
||||
// condition does not happen on this case.
|
||||
//
|
||||
if (mCountDown) {
|
||||
//
|
||||
// The performance counter counts down. Check for roll over condition.
|
||||
//
|
||||
if (CurrentTimer <= Timer) {
|
||||
Delta = Timer - CurrentTimer;
|
||||
} else {
|
||||
//
|
||||
// Handle one roll-over.
|
||||
//
|
||||
Delta = mCycle - (CurrentTimer - Timer) + 1;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// The performance counter counts up. Check for roll over condition.
|
||||
//
|
||||
if (CurrentTimer >= Timer) {
|
||||
Delta = CurrentTimer - Timer;
|
||||
} else {
|
||||
//
|
||||
// Handle one roll-over.
|
||||
//
|
||||
Delta = mCycle - (Timer - CurrentTimer) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (BOOLEAN) (Delta >= mTimeoutTicker);
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2006 - 2015, Intel Corporation. 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.
|
||||
#
|
||||
# Module Name:
|
||||
#
|
||||
# MpFuncs.S
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
# This is the assembly code for Multi-processor S3 support
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
.equ VacantFlag, 0x0
|
||||
.equ NotVacantFlag, 0xff
|
||||
|
||||
.equ LockLocation, RendezvousFunnelProcEnd - RendezvousFunnelProcStart
|
||||
.equ StackStartAddressLocation, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x08
|
||||
.equ StackSizeLocation, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x10
|
||||
.equ CProcedureLocation, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x18
|
||||
.equ GdtrLocation, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x20
|
||||
.equ IdtrLocation, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x2A
|
||||
.equ BufferStartLocation, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x34
|
||||
.equ Cr3OffsetLocation, RendezvousFunnelProcEnd - RendezvousFunnelProcStart + 0x38
|
||||
|
||||
#-------------------------------------------------------------------------------------
|
||||
#RendezvousFunnelProc procedure follows. All APs execute their procedure. This
|
||||
#procedure serializes all the AP processors through an Init sequence. It must be
|
||||
#noted that APs arrive here very raw...ie: real mode, no stack.
|
||||
#ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
|
||||
#IS IN MACHINE CODE.
|
||||
#-------------------------------------------------------------------------------------
|
||||
#RendezvousFunnelProc (&WakeUpBuffer,MemAddress);
|
||||
|
||||
.code:
|
||||
|
||||
ASM_GLOBAL ASM_PFX(RendezvousFunnelProc)
|
||||
ASM_PFX(RendezvousFunnelProc):
|
||||
RendezvousFunnelProcStart:
|
||||
|
||||
# At this point CS = 0x(vv00) and ip= 0x0.
|
||||
|
||||
.byte 0x8c,0xc8 # mov ax, cs
|
||||
.byte 0x8e,0xd8 # mov ds, ax
|
||||
.byte 0x8e,0xc0 # mov es, ax
|
||||
.byte 0x8e,0xd0 # mov ss, ax
|
||||
.byte 0x33,0xc0 # xor ax, ax
|
||||
.byte 0x8e,0xe0 # mov fs, ax
|
||||
.byte 0x8e,0xe8 # mov gs, ax
|
||||
|
||||
flat32Start:
|
||||
|
||||
.byte 0xBE
|
||||
.word BufferStartLocation
|
||||
.byte 0x66,0x8B,0x14 # mov edx,dword ptr [si] ; EDX is keeping the start address of wakeup buffer
|
||||
|
||||
.byte 0xBE
|
||||
.word Cr3OffsetLocation
|
||||
.byte 0x66,0x8B,0xC # mov ecx,dword ptr [si] ; ECX is keeping the value of CR3
|
||||
|
||||
.byte 0xBE
|
||||
.word GdtrLocation
|
||||
.byte 0x66 # db 66h
|
||||
.byte 0x2E,0xF,0x1,0x14 # lgdt fword ptr cs:[si]
|
||||
|
||||
.byte 0xBE
|
||||
.word IdtrLocation
|
||||
.byte 0x66 # db 66h
|
||||
.byte 0x2E,0xF,0x1,0x1C # lidt fword ptr cs:[si]
|
||||
|
||||
.byte 0x33,0xC0 # xor ax, ax
|
||||
.byte 0x8E,0xD8 # mov ds, ax
|
||||
|
||||
.byte 0xF,0x20,0xC0 # mov eax, cr0 ; Get control register 0
|
||||
.byte 0x66,0x83,0xC8,0x1 # or eax, 000000001h ; Set PE bit (bit #0)
|
||||
.byte 0xF,0x22,0xC0 # mov cr0, eax
|
||||
|
||||
FLAT32_JUMP:
|
||||
|
||||
.byte 0x66,0x67,0xEA # far jump
|
||||
.long 0x0 # 32-bit offset
|
||||
.word 0x20 # 16-bit selector
|
||||
|
||||
PMODE_ENTRY: # protected mode entry point
|
||||
|
||||
.byte 0x66,0xB8,0x18,0x0 # mov ax, 18h
|
||||
.byte 0x66,0x8E,0xD8 # mov ds, ax
|
||||
.byte 0x66,0x8E,0xC0 # mov es, ax
|
||||
.byte 0x66,0x8E,0xE0 # mov fs, ax
|
||||
.byte 0x66,0x8E,0xE8 # mov gs, ax
|
||||
.byte 0x66,0x8E,0xD0 # mov ss, ax ; Flat mode setup.
|
||||
|
||||
.byte 0xF,0x20,0xE0 # mov eax, cr4
|
||||
.byte 0xF,0xBA,0xE8,0x5 # bts eax, 5
|
||||
.byte 0xF,0x22,0xE0 # mov cr4, eax
|
||||
|
||||
.byte 0xF,0x22,0xD9 # mov cr3, ecx
|
||||
|
||||
.byte 0x8B,0xF2 # mov esi, edx ; Save wakeup buffer address
|
||||
|
||||
.byte 0xB9
|
||||
.long 0xC0000080 # mov ecx, 0c0000080h ; EFER MSR number.
|
||||
.byte 0xF,0x32 # rdmsr ; Read EFER.
|
||||
.byte 0xF,0xBA,0xE8,0x8 # bts eax, 8 ; Set LME=1.
|
||||
.byte 0xF,0x30 # wrmsr ; Write EFER.
|
||||
|
||||
.byte 0xF,0x20,0xC0 # mov eax, cr0 ; Read CR0.
|
||||
.byte 0xF,0xBA,0xE8,0x1F # bts eax, 31 ; Set PG=1.
|
||||
.byte 0xF,0x22,0xC0 # mov cr0, eax ; Write CR0.
|
||||
|
||||
LONG_JUMP:
|
||||
|
||||
.byte 0x67,0xEA # far jump
|
||||
.long 0x0 # 32-bit offset
|
||||
.word 0x38 # 16-bit selector
|
||||
|
||||
LongModeStart:
|
||||
|
||||
movw $0x30,%ax
|
||||
.byte 0x66
|
||||
movw %ax,%ds
|
||||
.byte 0x66
|
||||
movw %ax,%es
|
||||
.byte 0x66
|
||||
movw %ax,%ss
|
||||
|
||||
movl %esi,%edi
|
||||
addl $LockLocation, %edi
|
||||
movb $NotVacantFlag, %al
|
||||
TestLock:
|
||||
xchgb (%edi), %al
|
||||
cmpb $NotVacantFlag, %al
|
||||
jz TestLock
|
||||
|
||||
ProgramStack:
|
||||
|
||||
movl %esi,%edi
|
||||
addl $StackSizeLocation, %edi
|
||||
movq (%edi), %rax
|
||||
movl %esi,%edi
|
||||
addl $StackStartAddressLocation, %edi
|
||||
addq (%edi), %rax
|
||||
movq %rax, %rsp
|
||||
movq %rax, (%edi)
|
||||
|
||||
Releaselock:
|
||||
|
||||
movb $VacantFlag, %al
|
||||
movl %esi,%edi
|
||||
addl $LockLocation, %edi
|
||||
xchgb (%edi), %al
|
||||
|
||||
#
|
||||
# Call assembly function to initialize FPU.
|
||||
#
|
||||
movabsq $ASM_PFX(InitializeFloatingPointUnits), %rax
|
||||
subq $0x20, %rsp
|
||||
call *%rax
|
||||
addq $0x20, %rsp
|
||||
#
|
||||
# Call C Function
|
||||
#
|
||||
movl %esi,%edi
|
||||
addl $CProcedureLocation, %edi
|
||||
movq (%edi), %rax
|
||||
|
||||
testq %rax, %rax
|
||||
jz GoToSleep
|
||||
|
||||
subq $0x20, %rsp
|
||||
call *%rax
|
||||
addq $0x20, %rsp
|
||||
|
||||
GoToSleep:
|
||||
cli
|
||||
hlt
|
||||
jmp .-2
|
||||
|
||||
RendezvousFunnelProcEnd:
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------------
|
||||
# AsmGetAddressMap (&AddressMap);
|
||||
#-------------------------------------------------------------------------------------
|
||||
# comments here for definition of address map
|
||||
ASM_GLOBAL ASM_PFX(AsmGetAddressMap)
|
||||
ASM_PFX(AsmGetAddressMap):
|
||||
movabsq $RendezvousFunnelProcStart, %rax
|
||||
movq %rax, (%rcx)
|
||||
movq $(PMODE_ENTRY - RendezvousFunnelProcStart), 0x08(%rcx)
|
||||
movq $(FLAT32_JUMP - RendezvousFunnelProcStart), 0x10(%rcx)
|
||||
movq $(RendezvousFunnelProcEnd - RendezvousFunnelProcStart), 0x18(%rcx)
|
||||
movq $(LongModeStart - RendezvousFunnelProcStart), 0x20(%rcx)
|
||||
movq $(LONG_JUMP - RendezvousFunnelProcStart), 0x28(%rcx)
|
||||
ret
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
;------------------------------------------------------------------------------ ;
|
||||
; Copyright (c) 2006 - 2015, Intel Corporation. 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.
|
||||
;
|
||||
; Module Name:
|
||||
;
|
||||
; MpFuncs.asm
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; This is the assembly code for Multi-processor S3 support
|
||||
;
|
||||
;-------------------------------------------------------------------------------
|
||||
|
||||
EXTERN InitializeFloatingPointUnits:PROC
|
||||
|
||||
VacantFlag Equ 00h
|
||||
NotVacantFlag Equ 0ffh
|
||||
|
||||
LockLocation equ RendezvousFunnelProcEnd - RendezvousFunnelProcStart
|
||||
StackStartAddressLocation equ LockLocation + 08h
|
||||
StackSizeLocation equ LockLocation + 10h
|
||||
CProcedureLocation equ LockLocation + 18h
|
||||
GdtrLocation equ LockLocation + 20h
|
||||
IdtrLocation equ LockLocation + 2Ah
|
||||
BufferStartLocation equ LockLocation + 34h
|
||||
Cr3OffsetLocation equ LockLocation + 38h
|
||||
|
||||
;-------------------------------------------------------------------------------------
|
||||
;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
|
||||
;procedure serializes all the AP processors through an Init sequence. It must be
|
||||
;noted that APs arrive here very raw...ie: real mode, no stack.
|
||||
;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
|
||||
;IS IN MACHINE CODE.
|
||||
;-------------------------------------------------------------------------------------
|
||||
;RendezvousFunnelProc (&WakeUpBuffer,MemAddress);
|
||||
|
||||
;text SEGMENT
|
||||
.code
|
||||
|
||||
RendezvousFunnelProc PROC
|
||||
RendezvousFunnelProcStart::
|
||||
|
||||
; At this point CS = 0x(vv00) and ip= 0x0.
|
||||
|
||||
db 8ch, 0c8h ; mov ax, cs
|
||||
db 8eh, 0d8h ; mov ds, ax
|
||||
db 8eh, 0c0h ; mov es, ax
|
||||
db 8eh, 0d0h ; mov ss, ax
|
||||
db 33h, 0c0h ; xor ax, ax
|
||||
db 8eh, 0e0h ; mov fs, ax
|
||||
db 8eh, 0e8h ; mov gs, ax
|
||||
|
||||
flat32Start::
|
||||
|
||||
db 0BEh
|
||||
dw BufferStartLocation ; mov si, BufferStartLocation
|
||||
db 66h, 8Bh, 14h ; mov edx,dword ptr [si] ; EDX is keeping the start address of wakeup buffer
|
||||
|
||||
db 0BEh
|
||||
dw Cr3OffsetLocation ; mov si, Cr3Location
|
||||
db 66h, 8Bh, 0Ch ; mov ecx,dword ptr [si] ; ECX is keeping the value of CR3
|
||||
|
||||
db 0BEh
|
||||
dw GdtrLocation ; mov si, GdtrProfile
|
||||
db 66h ; db 66h
|
||||
db 2Eh, 0Fh, 01h, 14h ; lgdt fword ptr cs:[si]
|
||||
|
||||
db 0BEh
|
||||
dw IdtrLocation ; mov si, IdtrProfile
|
||||
db 66h ; db 66h
|
||||
db 2Eh, 0Fh, 01h, 1Ch ; lidt fword ptr cs:[si]
|
||||
|
||||
db 33h, 0C0h ; xor ax, ax
|
||||
db 8Eh, 0D8h ; mov ds, ax
|
||||
|
||||
db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Get control register 0
|
||||
db 66h, 83h, 0C8h, 01h ; or eax, 000000001h ; Set PE bit (bit #0)
|
||||
db 0Fh, 22h, 0C0h ; mov cr0, eax
|
||||
|
||||
FLAT32_JUMP::
|
||||
|
||||
db 66h, 67h, 0EAh ; far jump
|
||||
dd 0h ; 32-bit offset
|
||||
dw 20h ; 16-bit selector
|
||||
|
||||
PMODE_ENTRY:: ; protected mode entry point
|
||||
|
||||
db 66h, 0B8h, 18h, 00h ; mov ax, 18h
|
||||
db 66h, 8Eh, 0D8h ; mov ds, ax
|
||||
db 66h, 8Eh, 0C0h ; mov es, ax
|
||||
db 66h, 8Eh, 0E0h ; mov fs, ax
|
||||
db 66h, 8Eh, 0E8h ; mov gs, ax
|
||||
db 66h, 8Eh, 0D0h ; mov ss, ax ; Flat mode setup.
|
||||
|
||||
db 0Fh, 20h, 0E0h ; mov eax, cr4
|
||||
db 0Fh, 0BAh, 0E8h, 05h ; bts eax, 5
|
||||
db 0Fh, 22h, 0E0h ; mov cr4, eax
|
||||
|
||||
db 0Fh, 22h, 0D9h ; mov cr3, ecx
|
||||
|
||||
db 8Bh, 0F2h ; mov esi, edx ; Save wakeup buffer address
|
||||
|
||||
db 0B9h
|
||||
dd 0C0000080h ; mov ecx, 0c0000080h ; EFER MSR number.
|
||||
db 0Fh, 32h ; rdmsr ; Read EFER.
|
||||
db 0Fh, 0BAh, 0E8h, 08h ; bts eax, 8 ; Set LME=1.
|
||||
db 0Fh, 30h ; wrmsr ; Write EFER.
|
||||
|
||||
db 0Fh, 20h, 0C0h ; mov eax, cr0 ; Read CR0.
|
||||
db 0Fh, 0BAh, 0E8h, 1Fh ; bts eax, 31 ; Set PG=1.
|
||||
db 0Fh, 22h, 0C0h ; mov cr0, eax ; Write CR0.
|
||||
|
||||
LONG_JUMP::
|
||||
|
||||
db 67h, 0EAh ; far jump
|
||||
dd 0h ; 32-bit offset
|
||||
dw 38h ; 16-bit selector
|
||||
|
||||
LongModeStart::
|
||||
|
||||
mov ax, 30h
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov ss, ax
|
||||
|
||||
mov edi, esi
|
||||
add edi, LockLocation
|
||||
mov al, NotVacantFlag
|
||||
TestLock::
|
||||
xchg byte ptr [edi], al
|
||||
cmp al, NotVacantFlag
|
||||
jz TestLock
|
||||
|
||||
ProgramStack::
|
||||
|
||||
mov edi, esi
|
||||
add edi, StackSizeLocation
|
||||
mov rax, qword ptr [edi]
|
||||
mov edi, esi
|
||||
add edi, StackStartAddressLocation
|
||||
add rax, qword ptr [edi]
|
||||
mov rsp, rax
|
||||
mov qword ptr [edi], rax
|
||||
|
||||
Releaselock::
|
||||
|
||||
mov al, VacantFlag
|
||||
mov edi, esi
|
||||
add edi, LockLocation
|
||||
xchg byte ptr [edi], al
|
||||
|
||||
;
|
||||
; Call assembly function to initialize FPU.
|
||||
;
|
||||
mov rax, InitializeFloatingPointUnits
|
||||
sub rsp, 20h
|
||||
call rax
|
||||
add rsp, 20h
|
||||
|
||||
;
|
||||
; Call C Function
|
||||
;
|
||||
mov edi, esi
|
||||
add edi, CProcedureLocation
|
||||
mov rax, qword ptr [edi]
|
||||
|
||||
test rax, rax
|
||||
jz GoToSleep
|
||||
|
||||
sub rsp, 20h
|
||||
call rax
|
||||
add rsp, 20h
|
||||
|
||||
GoToSleep::
|
||||
cli
|
||||
hlt
|
||||
jmp $-2
|
||||
|
||||
RendezvousFunnelProcEnd::
|
||||
RendezvousFunnelProc ENDP
|
||||
|
||||
|
||||
;-------------------------------------------------------------------------------------
|
||||
; AsmGetAddressMap (&AddressMap);
|
||||
;-------------------------------------------------------------------------------------
|
||||
; comments here for definition of address map
|
||||
AsmGetAddressMap PROC
|
||||
mov rax, offset RendezvousFunnelProcStart
|
||||
mov qword ptr [rcx], rax
|
||||
mov qword ptr [rcx+8h], PMODE_ENTRY - RendezvousFunnelProcStart
|
||||
mov qword ptr [rcx+10h], FLAT32_JUMP - RendezvousFunnelProcStart
|
||||
mov qword ptr [rcx+18h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
|
||||
mov qword ptr [rcx+20h], LongModeStart - RendezvousFunnelProcStart
|
||||
mov qword ptr [rcx+28h], LONG_JUMP - RendezvousFunnelProcStart
|
||||
ret
|
||||
|
||||
AsmGetAddressMap ENDP
|
||||
|
||||
END
|
|
@ -0,0 +1,692 @@
|
|||
/** @file
|
||||
Page Fault (#PF) handler for X64 processors
|
||||
|
||||
Copyright (c) 2009 - 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "PiSmmCpuDxeSmm.h"
|
||||
|
||||
#define PAGE_TABLE_PAGES 8
|
||||
#define ACC_MAX_BIT BIT3
|
||||
LIST_ENTRY mPagePool = INITIALIZE_LIST_HEAD_VARIABLE (mPagePool);
|
||||
SPIN_LOCK mPFLock;
|
||||
BOOLEAN m1GPageTableSupport = FALSE;
|
||||
|
||||
/**
|
||||
Check if 1-GByte pages is supported by processor or not.
|
||||
|
||||
@retval TRUE 1-GByte pages is supported.
|
||||
@retval FALSE 1-GByte pages is not supported.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
Is1GPageSupport (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 RegEax;
|
||||
UINT32 RegEdx;
|
||||
|
||||
AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
|
||||
if (RegEax >= 0x80000001) {
|
||||
AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
|
||||
if ((RegEdx & BIT26) != 0) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Set sub-entries number in entry.
|
||||
|
||||
@param[in, out] Entry Pointer to entry
|
||||
@param[in] SubEntryNum Sub-entries number based on 0:
|
||||
0 means there is 1 sub-entry under this entry
|
||||
0x1ff means there is 512 sub-entries under this entry
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetSubEntriesNum (
|
||||
IN OUT UINT64 *Entry,
|
||||
IN UINT64 SubEntryNum
|
||||
)
|
||||
{
|
||||
//
|
||||
// Sub-entries number is saved in BIT52 to BIT60 (reserved field) in Entry
|
||||
//
|
||||
*Entry = BitFieldWrite64 (*Entry, 52, 60, SubEntryNum);
|
||||
}
|
||||
|
||||
/**
|
||||
Return sub-entries number in entry.
|
||||
|
||||
@param[in] Entry Pointer to entry
|
||||
|
||||
@return Sub-entries number based on 0:
|
||||
0 means there is 1 sub-entry under this entry
|
||||
0x1ff means there is 512 sub-entries under this entry
|
||||
**/
|
||||
UINT64
|
||||
GetSubEntriesNum (
|
||||
IN UINT64 *Entry
|
||||
)
|
||||
{
|
||||
//
|
||||
// Sub-entries number is saved in BIT52 to BIT60 (reserved field) in Entry
|
||||
//
|
||||
return BitFieldRead64 (*Entry, 52, 60);
|
||||
}
|
||||
|
||||
/**
|
||||
Create PageTable for SMM use.
|
||||
|
||||
@return The address of PML4 (to set CR3).
|
||||
|
||||
**/
|
||||
UINT32
|
||||
SmmInitPageTable (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS Pages;
|
||||
UINT64 *PTEntry;
|
||||
LIST_ENTRY *FreePage;
|
||||
UINTN Index;
|
||||
UINTN PageFaultHandlerHookAddress;
|
||||
IA32_IDT_GATE_DESCRIPTOR *IdtEntry;
|
||||
|
||||
//
|
||||
// Initialize spin lock
|
||||
//
|
||||
InitializeSpinLock (&mPFLock);
|
||||
|
||||
m1GPageTableSupport = Is1GPageSupport ();
|
||||
//
|
||||
// Generate PAE page table for the first 4GB memory space
|
||||
//
|
||||
Pages = Gen4GPageTable (PAGE_TABLE_PAGES + 1, FALSE);
|
||||
|
||||
//
|
||||
// Set IA32_PG_PMNT bit to mask this entry
|
||||
//
|
||||
PTEntry = (UINT64*)(UINTN)Pages;
|
||||
for (Index = 0; Index < 4; Index++) {
|
||||
PTEntry[Index] |= IA32_PG_PMNT;
|
||||
}
|
||||
|
||||
//
|
||||
// Fill Page-Table-Level4 (PML4) entry
|
||||
//
|
||||
PTEntry = (UINT64*)(UINTN)(Pages - EFI_PAGES_TO_SIZE (PAGE_TABLE_PAGES + 1));
|
||||
*PTEntry = Pages + PAGE_ATTRIBUTE_BITS;
|
||||
ZeroMem (PTEntry + 1, EFI_PAGE_SIZE - sizeof (*PTEntry));
|
||||
//
|
||||
// Set sub-entries number
|
||||
//
|
||||
SetSubEntriesNum (PTEntry, 3);
|
||||
|
||||
//
|
||||
// Add remaining pages to page pool
|
||||
//
|
||||
FreePage = (LIST_ENTRY*)(PTEntry + EFI_PAGE_SIZE / sizeof (*PTEntry));
|
||||
while ((UINTN)FreePage < Pages) {
|
||||
InsertTailList (&mPagePool, FreePage);
|
||||
FreePage += EFI_PAGE_SIZE / sizeof (*FreePage);
|
||||
}
|
||||
|
||||
if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
|
||||
//
|
||||
// Set own Page Fault entry instead of the default one, because SMM Profile
|
||||
// feature depends on IRET instruction to do Single Step
|
||||
//
|
||||
PageFaultHandlerHookAddress = (UINTN)PageFaultIdtHandlerSmmProfile;
|
||||
IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) gcSmiIdtr.Base;
|
||||
IdtEntry += EXCEPT_IA32_PAGE_FAULT;
|
||||
IdtEntry->Bits.OffsetLow = (UINT16)PageFaultHandlerHookAddress;
|
||||
IdtEntry->Bits.Reserved_0 = 0;
|
||||
IdtEntry->Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
|
||||
IdtEntry->Bits.OffsetHigh = (UINT16)(PageFaultHandlerHookAddress >> 16);
|
||||
IdtEntry->Bits.OffsetUpper = (UINT32)(PageFaultHandlerHookAddress >> 32);
|
||||
IdtEntry->Bits.Reserved_1 = 0;
|
||||
} else {
|
||||
//
|
||||
// Register Smm Page Fault Handler
|
||||
//
|
||||
SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_PAGE_FAULT, SmiPFHandler);
|
||||
}
|
||||
|
||||
//
|
||||
// Additional SMM IDT initialization for SMM stack guard
|
||||
//
|
||||
if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
|
||||
InitializeIDTSmmStackGuard ();
|
||||
}
|
||||
|
||||
//
|
||||
// Return the address of PML4 (to set CR3)
|
||||
//
|
||||
return (UINT32)(UINTN)PTEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
Set access record in entry.
|
||||
|
||||
@param[in, out] Entry Pointer to entry
|
||||
@param[in] Acc Access record value
|
||||
|
||||
**/
|
||||
VOID
|
||||
SetAccNum (
|
||||
IN OUT UINT64 *Entry,
|
||||
IN UINT64 Acc
|
||||
)
|
||||
{
|
||||
//
|
||||
// Access record is saved in BIT9 to BIT11 (reserved field) in Entry
|
||||
//
|
||||
*Entry = BitFieldWrite64 (*Entry, 9, 11, Acc);
|
||||
}
|
||||
|
||||
/**
|
||||
Return access record in entry.
|
||||
|
||||
@param[in] Entry Pointer to entry
|
||||
|
||||
@return Access record value.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
GetAccNum (
|
||||
IN UINT64 *Entry
|
||||
)
|
||||
{
|
||||
//
|
||||
// Access record is saved in BIT9 to BIT11 (reserved field) in Entry
|
||||
//
|
||||
return BitFieldRead64 (*Entry, 9, 11);
|
||||
}
|
||||
|
||||
/**
|
||||
Return and update the access record in entry.
|
||||
|
||||
@param[in, out] Entry Pointer to entry
|
||||
|
||||
@return Access record value.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
GetAndUpdateAccNum (
|
||||
IN OUT UINT64 *Entry
|
||||
)
|
||||
{
|
||||
UINT64 Acc;
|
||||
|
||||
Acc = GetAccNum (Entry);
|
||||
if ((*Entry & IA32_PG_A) != 0) {
|
||||
//
|
||||
// If this entry has been accessed, clear access flag in Entry and update access record
|
||||
// to the initial value 7, adding ACC_MAX_BIT is to make it larger than others
|
||||
//
|
||||
*Entry &= ~(UINT64)(UINTN)IA32_PG_A;
|
||||
SetAccNum (Entry, 0x7);
|
||||
return (0x7 + ACC_MAX_BIT);
|
||||
} else {
|
||||
if (Acc != 0) {
|
||||
//
|
||||
// If the access record is not the smallest value 0, minus 1 and update the access record field
|
||||
//
|
||||
SetAccNum (Entry, Acc - 1);
|
||||
}
|
||||
}
|
||||
return Acc;
|
||||
}
|
||||
|
||||
/**
|
||||
Reclaim free pages for PageFault handler.
|
||||
|
||||
Search the whole entries tree to find the leaf entry that has the smallest
|
||||
access record value. Insert the page pointed by this leaf entry into the
|
||||
page pool. And check its upper entries if need to be inserted into the page
|
||||
pool or not.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ReclaimPages (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT64 *Pml4;
|
||||
UINT64 *Pdpt;
|
||||
UINT64 *Pdt;
|
||||
UINTN Pml4Index;
|
||||
UINTN PdptIndex;
|
||||
UINTN PdtIndex;
|
||||
UINTN MinPml4;
|
||||
UINTN MinPdpt;
|
||||
UINTN MinPdt;
|
||||
UINT64 MinAcc;
|
||||
UINT64 Acc;
|
||||
UINT64 SubEntriesNum;
|
||||
BOOLEAN PML4EIgnore;
|
||||
BOOLEAN PDPTEIgnore;
|
||||
UINT64 *ReleasePageAddress;
|
||||
|
||||
Pml4 = NULL;
|
||||
Pdpt = NULL;
|
||||
Pdt = NULL;
|
||||
MinAcc = (UINT64)-1;
|
||||
MinPml4 = (UINTN)-1;
|
||||
MinPdpt = (UINTN)-1;
|
||||
MinPdt = (UINTN)-1;
|
||||
Acc = 0;
|
||||
ReleasePageAddress = 0;
|
||||
|
||||
//
|
||||
// First, find the leaf entry has the smallest access record value
|
||||
//
|
||||
Pml4 = (UINT64*)(UINTN)(AsmReadCr3 () & gPhyMask);
|
||||
for (Pml4Index = 0; Pml4Index < EFI_PAGE_SIZE / sizeof (*Pml4); Pml4Index++) {
|
||||
if ((Pml4[Pml4Index] & IA32_PG_P) == 0 || (Pml4[Pml4Index] & IA32_PG_PMNT) != 0) {
|
||||
//
|
||||
// If the PML4 entry is not present or is masked, skip it
|
||||
//
|
||||
continue;
|
||||
}
|
||||
Pdpt = (UINT64*)(UINTN)(Pml4[Pml4Index] & gPhyMask);
|
||||
PML4EIgnore = FALSE;
|
||||
for (PdptIndex = 0; PdptIndex < EFI_PAGE_SIZE / sizeof (*Pdpt); PdptIndex++) {
|
||||
if ((Pdpt[PdptIndex] & IA32_PG_P) == 0 || (Pdpt[PdptIndex] & IA32_PG_PMNT) != 0) {
|
||||
//
|
||||
// If the PDPT entry is not present or is masked, skip it
|
||||
//
|
||||
if ((Pdpt[PdptIndex] & IA32_PG_PMNT) != 0) {
|
||||
//
|
||||
// If the PDPT entry is masked, we will ignore checking the PML4 entry
|
||||
//
|
||||
PML4EIgnore = TRUE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ((Pdpt[PdptIndex] & IA32_PG_PS) == 0) {
|
||||
//
|
||||
// It's not 1-GByte pages entry, it should be a PDPT entry,
|
||||
// we will not check PML4 entry more
|
||||
//
|
||||
PML4EIgnore = TRUE;
|
||||
Pdt = (UINT64*)(UINTN)(Pdpt[PdptIndex] & gPhyMask);
|
||||
PDPTEIgnore = FALSE;
|
||||
for (PdtIndex = 0; PdtIndex < EFI_PAGE_SIZE / sizeof(*Pdt); PdtIndex++) {
|
||||
if ((Pdt[PdtIndex] & IA32_PG_P) == 0 || (Pdt[PdtIndex] & IA32_PG_PMNT) != 0) {
|
||||
//
|
||||
// If the PD entry is not present or is masked, skip it
|
||||
//
|
||||
if ((Pdt[PdtIndex] & IA32_PG_PMNT) != 0) {
|
||||
//
|
||||
// If the PD entry is masked, we will not PDPT entry more
|
||||
//
|
||||
PDPTEIgnore = TRUE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ((Pdt[PdtIndex] & IA32_PG_PS) == 0) {
|
||||
//
|
||||
// It's not 2 MByte page table entry, it should be PD entry
|
||||
// we will find the entry has the smallest access record value
|
||||
//
|
||||
PDPTEIgnore = TRUE;
|
||||
Acc = GetAndUpdateAccNum (Pdt + PdtIndex);
|
||||
if (Acc < MinAcc) {
|
||||
//
|
||||
// If the PD entry has the smallest access record value,
|
||||
// save the Page address to be released
|
||||
//
|
||||
MinAcc = Acc;
|
||||
MinPml4 = Pml4Index;
|
||||
MinPdpt = PdptIndex;
|
||||
MinPdt = PdtIndex;
|
||||
ReleasePageAddress = Pdt + PdtIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!PDPTEIgnore) {
|
||||
//
|
||||
// If this PDPT entry has no PDT entries pointer to 4 KByte pages,
|
||||
// it should only has the entries point to 2 MByte Pages
|
||||
//
|
||||
Acc = GetAndUpdateAccNum (Pdpt + PdptIndex);
|
||||
if (Acc < MinAcc) {
|
||||
//
|
||||
// If the PDPT entry has the smallest access record value,
|
||||
// save the Page address to be released
|
||||
//
|
||||
MinAcc = Acc;
|
||||
MinPml4 = Pml4Index;
|
||||
MinPdpt = PdptIndex;
|
||||
MinPdt = (UINTN)-1;
|
||||
ReleasePageAddress = Pdpt + PdptIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!PML4EIgnore) {
|
||||
//
|
||||
// If PML4 entry has no the PDPT entry pointer to 2 MByte pages,
|
||||
// it should only has the entries point to 1 GByte Pages
|
||||
//
|
||||
Acc = GetAndUpdateAccNum (Pml4 + Pml4Index);
|
||||
if (Acc < MinAcc) {
|
||||
//
|
||||
// If the PML4 entry has the smallest access record value,
|
||||
// save the Page address to be released
|
||||
//
|
||||
MinAcc = Acc;
|
||||
MinPml4 = Pml4Index;
|
||||
MinPdpt = (UINTN)-1;
|
||||
MinPdt = (UINTN)-1;
|
||||
ReleasePageAddress = Pml4 + Pml4Index;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// Make sure one PML4/PDPT/PD entry is selected
|
||||
//
|
||||
ASSERT (MinAcc != (UINT64)-1);
|
||||
|
||||
//
|
||||
// Secondly, insert the page pointed by this entry into page pool and clear this entry
|
||||
//
|
||||
InsertTailList (&mPagePool, (LIST_ENTRY*)(UINTN)(*ReleasePageAddress & gPhyMask));
|
||||
*ReleasePageAddress = 0;
|
||||
|
||||
//
|
||||
// Lastly, check this entry's upper entries if need to be inserted into page pool
|
||||
// or not
|
||||
//
|
||||
while (TRUE) {
|
||||
if (MinPdt != (UINTN)-1) {
|
||||
//
|
||||
// If 4 KByte Page Table is released, check the PDPT entry
|
||||
//
|
||||
Pdpt = (UINT64*)(UINTN)(Pml4[MinPml4] & gPhyMask);
|
||||
SubEntriesNum = GetSubEntriesNum(Pdpt + MinPdpt);
|
||||
if (SubEntriesNum == 0) {
|
||||
//
|
||||
// Release the empty Page Directory table if there was no more 4 KByte Page Table entry
|
||||
// clear the Page directory entry
|
||||
//
|
||||
InsertTailList (&mPagePool, (LIST_ENTRY*)(UINTN)(Pdpt[MinPdpt] & gPhyMask));
|
||||
Pdpt[MinPdpt] = 0;
|
||||
//
|
||||
// Go on checking the PML4 table
|
||||
//
|
||||
MinPdt = (UINTN)-1;
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Update the sub-entries filed in PDPT entry and exit
|
||||
//
|
||||
SetSubEntriesNum (Pdpt + MinPdpt, SubEntriesNum - 1);
|
||||
break;
|
||||
}
|
||||
if (MinPdpt != (UINTN)-1) {
|
||||
//
|
||||
// One 2MB Page Table is released or Page Directory table is released, check the PML4 entry
|
||||
//
|
||||
SubEntriesNum = GetSubEntriesNum (Pml4 + MinPml4);
|
||||
if (SubEntriesNum == 0) {
|
||||
//
|
||||
// Release the empty PML4 table if there was no more 1G KByte Page Table entry
|
||||
// clear the Page directory entry
|
||||
//
|
||||
InsertTailList (&mPagePool, (LIST_ENTRY*)(UINTN)(Pml4[MinPml4] & gPhyMask));
|
||||
Pml4[MinPml4] = 0;
|
||||
MinPdpt = (UINTN)-1;
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// Update the sub-entries filed in PML4 entry and exit
|
||||
//
|
||||
SetSubEntriesNum (Pml4 + MinPml4, SubEntriesNum - 1);
|
||||
break;
|
||||
}
|
||||
//
|
||||
// PLM4 table has been released before, exit it
|
||||
//
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Allocate free Page for PageFault handler use.
|
||||
|
||||
@return Page address.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
AllocPage (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT64 RetVal;
|
||||
|
||||
if (IsListEmpty (&mPagePool)) {
|
||||
//
|
||||
// If page pool is empty, reclaim the used pages and insert one into page pool
|
||||
//
|
||||
ReclaimPages ();
|
||||
}
|
||||
|
||||
//
|
||||
// Get one free page and remove it from page pool
|
||||
//
|
||||
RetVal = (UINT64)(UINTN)mPagePool.ForwardLink;
|
||||
RemoveEntryList (mPagePool.ForwardLink);
|
||||
//
|
||||
// Clean this page and return
|
||||
//
|
||||
ZeroMem ((VOID*)(UINTN)RetVal, EFI_PAGE_SIZE);
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
/**
|
||||
Page Fault handler for SMM use.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SmiDefaultPFHandler (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT64 *PageTable;
|
||||
UINT64 *Pml4;
|
||||
UINT64 PFAddress;
|
||||
UINTN StartBit;
|
||||
UINTN EndBit;
|
||||
UINT64 PTIndex;
|
||||
UINTN Index;
|
||||
SMM_PAGE_SIZE_TYPE PageSize;
|
||||
UINTN NumOfPages;
|
||||
UINTN PageAttribute;
|
||||
EFI_STATUS Status;
|
||||
UINT64 *UpperEntry;
|
||||
|
||||
//
|
||||
// Set default SMM page attribute
|
||||
//
|
||||
PageSize = SmmPageSize2M;
|
||||
NumOfPages = 1;
|
||||
PageAttribute = 0;
|
||||
|
||||
EndBit = 0;
|
||||
Pml4 = (UINT64*)(AsmReadCr3 () & gPhyMask);
|
||||
PFAddress = AsmReadCr2 ();
|
||||
|
||||
Status = GetPlatformPageTableAttribute (PFAddress, &PageSize, &NumOfPages, &PageAttribute);
|
||||
//
|
||||
// If platform not support page table attribute, set default SMM page attribute
|
||||
//
|
||||
if (Status != EFI_SUCCESS) {
|
||||
PageSize = SmmPageSize2M;
|
||||
NumOfPages = 1;
|
||||
PageAttribute = 0;
|
||||
}
|
||||
if (PageSize >= MaxSmmPageSizeType) {
|
||||
PageSize = SmmPageSize2M;
|
||||
}
|
||||
if (NumOfPages > 512) {
|
||||
NumOfPages = 512;
|
||||
}
|
||||
|
||||
switch (PageSize) {
|
||||
case SmmPageSize4K:
|
||||
//
|
||||
// BIT12 to BIT20 is Page Table index
|
||||
//
|
||||
EndBit = 12;
|
||||
break;
|
||||
case SmmPageSize2M:
|
||||
//
|
||||
// BIT21 to BIT29 is Page Directory index
|
||||
//
|
||||
EndBit = 21;
|
||||
PageAttribute |= (UINTN)IA32_PG_PS;
|
||||
break;
|
||||
case SmmPageSize1G:
|
||||
if (!m1GPageTableSupport) {
|
||||
DEBUG ((EFI_D_ERROR, "1-GByte pages is not supported!"));
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
//
|
||||
// BIT30 to BIT38 is Page Directory Pointer Table index
|
||||
//
|
||||
EndBit = 30;
|
||||
PageAttribute |= (UINTN)IA32_PG_PS;
|
||||
break;
|
||||
default:
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
|
||||
//
|
||||
// If execute-disable is enabled, set NX bit
|
||||
//
|
||||
if (mXdEnabled) {
|
||||
PageAttribute |= IA32_PG_NX;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < NumOfPages; Index++) {
|
||||
PageTable = Pml4;
|
||||
UpperEntry = NULL;
|
||||
for (StartBit = 39; StartBit > EndBit; StartBit -= 9) {
|
||||
PTIndex = BitFieldRead64 (PFAddress, StartBit, StartBit + 8);
|
||||
if ((PageTable[PTIndex] & IA32_PG_P) == 0) {
|
||||
//
|
||||
// If the entry is not present, allocate one page from page pool for it
|
||||
//
|
||||
PageTable[PTIndex] = AllocPage () | PAGE_ATTRIBUTE_BITS;
|
||||
} else {
|
||||
//
|
||||
// Save the upper entry address
|
||||
//
|
||||
UpperEntry = PageTable + PTIndex;
|
||||
}
|
||||
//
|
||||
// BIT9 to BIT11 of entry is used to save access record,
|
||||
// initialize value is 7
|
||||
//
|
||||
PageTable[PTIndex] |= (UINT64)IA32_PG_A;
|
||||
SetAccNum (PageTable + PTIndex, 7);
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & gPhyMask);
|
||||
}
|
||||
|
||||
PTIndex = BitFieldRead64 (PFAddress, StartBit, StartBit + 8);
|
||||
if ((PageTable[PTIndex] & IA32_PG_P) != 0) {
|
||||
//
|
||||
// Check if the entry has already existed, this issue may occur when the different
|
||||
// size page entries created under the same entry
|
||||
//
|
||||
DEBUG ((EFI_D_ERROR, "PageTable = %lx, PTIndex = %x, PageTable[PTIndex] = %lx\n", PageTable, PTIndex, PageTable[PTIndex]));
|
||||
DEBUG ((EFI_D_ERROR, "New page table overlapped with old page table!\n"));
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
//
|
||||
// Fill the new entry
|
||||
//
|
||||
PageTable[PTIndex] = (PFAddress & gPhyMask & ~((1ull << EndBit) - 1)) |
|
||||
PageAttribute | IA32_PG_A | PAGE_ATTRIBUTE_BITS;
|
||||
if (UpperEntry != NULL) {
|
||||
SetSubEntriesNum (UpperEntry, GetSubEntriesNum (UpperEntry) + 1);
|
||||
}
|
||||
//
|
||||
// Get the next page address if we need to create more page tables
|
||||
//
|
||||
PFAddress += (1ull << EndBit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
ThePage Fault handler wrapper 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
|
||||
)
|
||||
{
|
||||
UINTN PFAddress;
|
||||
|
||||
ASSERT (InterruptType == EXCEPT_IA32_PAGE_FAULT);
|
||||
|
||||
AcquireSpinLock (&mPFLock);
|
||||
|
||||
PFAddress = AsmReadCr2 ();
|
||||
|
||||
//
|
||||
// If a page fault occurs in SMRAM range, it should be in a SMM stack guard page.
|
||||
//
|
||||
if ((FeaturePcdGet (PcdCpuSmmStackGuard)) &&
|
||||
(PFAddress >= mCpuHotPlugData.SmrrBase) &&
|
||||
(PFAddress < (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize))) {
|
||||
DEBUG ((EFI_D_ERROR, "SMM stack overflow!\n"));
|
||||
CpuDeadLoop ();
|
||||
}
|
||||
|
||||
//
|
||||
// If a page fault occurs in SMM range
|
||||
//
|
||||
if ((PFAddress < mCpuHotPlugData.SmrrBase) ||
|
||||
(PFAddress >= mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) {
|
||||
if ((SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_ID) != 0) {
|
||||
DEBUG ((EFI_D_ERROR, "Code executed on IP(0x%lx) out of SMM range after SMM is locked!\n", PFAddress));
|
||||
DEBUG_CODE (
|
||||
DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextX64->Rsp);
|
||||
);
|
||||
CpuDeadLoop ();
|
||||
}
|
||||
}
|
||||
|
||||
if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {
|
||||
SmmProfilePFHandler (
|
||||
SystemContext.SystemContextX64->Rip,
|
||||
SystemContext.SystemContextX64->ExceptionData
|
||||
);
|
||||
} else {
|
||||
SmiDefaultPFHandler ();
|
||||
}
|
||||
|
||||
ReleaseSpinLock (&mPFLock);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/** @file
|
||||
Semaphore mechanism to indicate to the BSP that an AP has exited SMM
|
||||
after SMBASE relocation.
|
||||
|
||||
Copyright (c) 2009 - 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "PiSmmCpuDxeSmm.h"
|
||||
|
||||
extern UINT32 mSmmRelocationOriginalAddressPtr32;
|
||||
extern UINT32 mRebasedFlagAddr32;
|
||||
|
||||
UINTN mSmmRelocationOriginalAddress;
|
||||
volatile BOOLEAN *mRebasedFlag;
|
||||
|
||||
/**
|
||||
AP Semaphore operation in 32-bit mode while BSP runs in 64-bit mode.
|
||||
**/
|
||||
VOID
|
||||
SmmRelocationSemaphoreComplete32 (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
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
|
||||
)
|
||||
{
|
||||
SMRAM_SAVE_STATE_MAP *CpuState;
|
||||
UINTN TempValue;
|
||||
|
||||
mRebasedFlag = RebasedFlag;
|
||||
mRebasedFlagAddr32 = (UINT32)(UINTN)mRebasedFlag;
|
||||
|
||||
CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
|
||||
mSmmRelocationOriginalAddress = HookReturnFromSmm (
|
||||
CpuIndex,
|
||||
CpuState,
|
||||
(UINT64)(UINTN)&SmmRelocationSemaphoreComplete32,
|
||||
(UINT64)(UINTN)&SmmRelocationSemaphoreComplete
|
||||
);
|
||||
|
||||
//
|
||||
// Use temp value to fix ICC complier warning
|
||||
//
|
||||
TempValue = (UINTN)&mSmmRelocationOriginalAddress;
|
||||
mSmmRelocationOriginalAddressPtr32 = (UINT32)TempValue;
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2009 - 2016, Intel Corporation. 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.
|
||||
#
|
||||
# Module Name:
|
||||
#
|
||||
# SmiEntry.S
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
# Code template of the SMI handler for a particular processor
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
ASM_GLOBAL ASM_PFX(gcSmiHandlerTemplate)
|
||||
ASM_GLOBAL ASM_PFX(gcSmiHandlerSize)
|
||||
ASM_GLOBAL ASM_PFX(gcSmiHandlerOffset)
|
||||
ASM_GLOBAL ASM_PFX(gSmiCr3)
|
||||
ASM_GLOBAL ASM_PFX(gSmiStack)
|
||||
ASM_GLOBAL ASM_PFX(gSmbase)
|
||||
ASM_GLOBAL ASM_PFX(gSmiHandlerIdtr)
|
||||
|
||||
#
|
||||
# Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR
|
||||
#
|
||||
.equ DSC_OFFSET, 0xfb00
|
||||
.equ DSC_GDTPTR, 0x48
|
||||
.equ DSC_GDTSIZ, 0x50
|
||||
.equ DSC_CS, 0x14
|
||||
.equ DSC_DS, 0x16
|
||||
.equ DSC_SS, 0x18
|
||||
.equ DSC_OTHERSEG, 0x1A
|
||||
#
|
||||
# Constants relating to CPU State Save Area
|
||||
#
|
||||
.equ SSM_DR6, 0xffd0
|
||||
.equ SSM_DR7, 0xffc8
|
||||
|
||||
.equ PROTECT_MODE_CS, 0x08
|
||||
.equ PROTECT_MODE_DS, 0x20
|
||||
.equ LONG_MODE_CS, 0x38
|
||||
.equ TSS_SEGMENT, 0x40
|
||||
.equ GDT_SIZE, 0x50
|
||||
|
||||
.text
|
||||
|
||||
ASM_PFX(gcSmiHandlerOffset): .word _SmiHandler - _SmiEntryPoint + 0x8000
|
||||
|
||||
ASM_PFX(gcSmiHandlerTemplate):
|
||||
|
||||
_SmiEntryPoint:
|
||||
#
|
||||
# The encoding of BX in 16-bit addressing mode is the same as of RDI in 64-
|
||||
# bit addressing mode. And that coincidence has been used in the following
|
||||
# "64-bit like" 16-bit code. Be aware that once RDI is referenced as a
|
||||
# base address register, it is actually BX that is referenced.
|
||||
#
|
||||
.byte 0xbb # mov bx, imm16
|
||||
.word _GdtDesc - _SmiEntryPoint + 0x8000
|
||||
#
|
||||
# fix GDT descriptor
|
||||
#
|
||||
.byte 0x2e,0xa1 # mov ax, cs:[offset16]
|
||||
.word DSC_OFFSET + DSC_GDTSIZ
|
||||
.byte 0x48 # dec ax
|
||||
.byte 0x2e
|
||||
movl %eax, (%rdi) # mov cs:[bx], ax
|
||||
.byte 0x66,0x2e,0xa1 # mov eax, cs:[offset16]
|
||||
.word DSC_OFFSET + DSC_GDTPTR
|
||||
.byte 0x2e
|
||||
movw %ax, 2(%rdi)
|
||||
.byte 0x66,0x2e
|
||||
lgdt (%rdi)
|
||||
#
|
||||
# Patch ProtectedMode Segment
|
||||
#
|
||||
.byte 0xb8
|
||||
.word PROTECT_MODE_CS
|
||||
.byte 0x2e
|
||||
movl %eax, -2(%rdi)
|
||||
#
|
||||
# Patch ProtectedMode entry
|
||||
#
|
||||
.byte 0x66, 0xbf # mov edi, SMBASE
|
||||
ASM_PFX(gSmbase): .space 4
|
||||
lea ((ProtectedMode - _SmiEntryPoint) + 0x8000)(%edi), %ax
|
||||
.byte 0x2e
|
||||
movw %ax, -6(%rdi)
|
||||
#
|
||||
# Switch into ProtectedMode
|
||||
#
|
||||
movq %cr0, %rbx
|
||||
.byte 0x66
|
||||
andl $0x9ffafff3, %ebx
|
||||
.byte 0x66
|
||||
orl $0x00000023, %ebx
|
||||
|
||||
movq %rbx, %cr0
|
||||
.byte 0x66, 0xea
|
||||
.space 6
|
||||
|
||||
_GdtDesc: .space 6
|
||||
|
||||
ProtectedMode:
|
||||
movw $PROTECT_MODE_DS, %ax
|
||||
movl %eax, %ds
|
||||
movl %eax, %es
|
||||
movl %eax, %fs
|
||||
movl %eax, %gs
|
||||
movl %eax, %ss
|
||||
.byte 0xbc # mov esp, imm32
|
||||
ASM_PFX(gSmiStack): .space 4
|
||||
jmp ProtFlatMode
|
||||
|
||||
ProtFlatMode:
|
||||
.byte 0xb8
|
||||
ASM_PFX(gSmiCr3): .space 4
|
||||
movq %rax, %cr3
|
||||
movl $0x668,%eax # as cr4.PGE is not set here, refresh cr3
|
||||
movq %rax, %cr4 # in PreModifyMtrrs() to flush TLB.
|
||||
# Load TSS
|
||||
subl $8, %esp # reserve room in stack
|
||||
sgdt (%rsp)
|
||||
movl 2(%rsp), %eax # eax = GDT base
|
||||
addl $8, %esp
|
||||
movb $0x89, %dl
|
||||
movb %dl, (TSS_SEGMENT + 5)(%rax) # clear busy flag
|
||||
movl $TSS_SEGMENT, %eax
|
||||
ltr %ax
|
||||
|
||||
#
|
||||
# Switch to LongMode
|
||||
#
|
||||
pushq $LONG_MODE_CS # push cs hardcore here
|
||||
call Base # push return address for retf later
|
||||
Base:
|
||||
addl $(LongMode - Base), (%rsp) # offset for far retf, seg is the 1st arg
|
||||
movl $0xc0000080, %ecx
|
||||
rdmsr
|
||||
orb $1,%ah
|
||||
wrmsr
|
||||
movq %cr0, %rbx
|
||||
orl $0x080010000, %ebx # enable paging + WP
|
||||
movq %rbx, %cr0
|
||||
retf
|
||||
LongMode: # long mode (64-bit code) starts here
|
||||
movabsq $ASM_PFX(gSmiHandlerIdtr), %rax
|
||||
lidt (%rax)
|
||||
lea (DSC_OFFSET)(%rdi), %ebx
|
||||
movw DSC_DS(%rbx), %ax
|
||||
movl %eax,%ds
|
||||
movw DSC_OTHERSEG(%rbx), %ax
|
||||
movl %eax,%es
|
||||
movl %eax,%fs
|
||||
movl %eax,%gs
|
||||
movw DSC_SS(%rbx), %ax
|
||||
movl %eax,%ss
|
||||
# jmp _SmiHandler ; instruction is not needed
|
||||
|
||||
_SmiHandler:
|
||||
# below step is needed, because STM does not run above code.
|
||||
# we have to run below code to set IDT/CR0/CR4
|
||||
movabsq $ASM_PFX(gSmiHandlerIdtr), %rax
|
||||
lidt (%rax)
|
||||
movq %cr0, %rax
|
||||
orl $0x00000022, %eax
|
||||
orl $0x00010000, %eax # enable WP
|
||||
movq %rax, %cr0
|
||||
movq %cr4, %rax
|
||||
movl $0x668, %eax # as cr4.PGE is not set here, refresh cr3
|
||||
movq %rax, %cr4 # in PreModifyMtrrs() to flush TLB.
|
||||
# STM init finish
|
||||
|
||||
movq (%rsp), %rbx
|
||||
# Save FP registers
|
||||
|
||||
subq $0x208, %rsp
|
||||
.byte 0x48 # FXSAVE64
|
||||
fxsave (%rsp)
|
||||
|
||||
addq $-0x20, %rsp
|
||||
|
||||
movq %rbx, %rcx
|
||||
movabsq $ASM_PFX(CpuSmmDebugEntry), %rax
|
||||
call *%rax
|
||||
|
||||
movq %rbx, %rcx
|
||||
movabsq $ASM_PFX(SmiRendezvous), %rax
|
||||
call *%rax
|
||||
|
||||
movq %rbx, %rcx
|
||||
movabsq $ASM_PFX(CpuSmmDebugExit), %rax
|
||||
call *%rax
|
||||
|
||||
addq $0x20, %rsp
|
||||
|
||||
#
|
||||
# Restore FP registers
|
||||
#
|
||||
.byte 0x48 # FXRSTOR64
|
||||
fxrstor (%rsp)
|
||||
|
||||
rsm
|
||||
|
||||
ASM_PFX(gcSmiHandlerSize): .word . - _SmiEntryPoint
|
|
@ -0,0 +1,214 @@
|
|||
;------------------------------------------------------------------------------ ;
|
||||
; Copyright (c) 2009 - 2016, Intel Corporation. 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.
|
||||
;
|
||||
; Module Name:
|
||||
;
|
||||
; SmiEntry.asm
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; Code template of the SMI handler for a particular processor
|
||||
;
|
||||
;-------------------------------------------------------------------------------
|
||||
|
||||
;
|
||||
; Variables referenced by C code
|
||||
;
|
||||
EXTERNDEF SmiRendezvous:PROC
|
||||
EXTERNDEF CpuSmmDebugEntry:PROC
|
||||
EXTERNDEF CpuSmmDebugExit:PROC
|
||||
EXTERNDEF gcSmiHandlerTemplate:BYTE
|
||||
EXTERNDEF gcSmiHandlerSize:WORD
|
||||
EXTERNDEF gcSmiHandlerOffset:WORD
|
||||
EXTERNDEF gSmiCr3:DWORD
|
||||
EXTERNDEF gSmiStack:DWORD
|
||||
EXTERNDEF gSmbase:DWORD
|
||||
EXTERNDEF gSmiHandlerIdtr:FWORD
|
||||
|
||||
|
||||
;
|
||||
; Constants relating to TXT_PROCESSOR_SMM_DESCRIPTOR
|
||||
;
|
||||
DSC_OFFSET EQU 0fb00h
|
||||
DSC_GDTPTR EQU 48h
|
||||
DSC_GDTSIZ EQU 50h
|
||||
DSC_CS EQU 14h
|
||||
DSC_DS EQU 16h
|
||||
DSC_SS EQU 18h
|
||||
DSC_OTHERSEG EQU 1Ah
|
||||
;
|
||||
; Constants relating to CPU State Save Area
|
||||
;
|
||||
SSM_DR6 EQU 0ffd0h
|
||||
SSM_DR7 EQU 0ffc8h
|
||||
|
||||
PROTECT_MODE_CS EQU 08h
|
||||
PROTECT_MODE_DS EQU 20h
|
||||
LONG_MODE_CS EQU 38h
|
||||
TSS_SEGMENT EQU 40h
|
||||
GDT_SIZE EQU 50h
|
||||
|
||||
.const
|
||||
|
||||
gcSmiHandlerOffset DW _SmiHandler - _SmiEntryPoint + 8000h
|
||||
|
||||
.code
|
||||
|
||||
gcSmiHandlerTemplate LABEL BYTE
|
||||
|
||||
_SmiEntryPoint:
|
||||
;
|
||||
; The encoding of BX in 16-bit addressing mode is the same as of RDI in 64-
|
||||
; bit addressing mode. And that coincidence has been used in the following
|
||||
; "64-bit like" 16-bit code. Be aware that once RDI is referenced as a
|
||||
; base address register, it is actually BX that is referenced.
|
||||
;
|
||||
DB 0bbh ; mov bx, imm16
|
||||
DW offset _GdtDesc - _SmiEntryPoint + 8000h ; bx = GdtDesc offset
|
||||
; fix GDT descriptor
|
||||
DB 2eh, 0a1h ; mov ax, cs:[offset16]
|
||||
DW DSC_OFFSET + DSC_GDTSIZ
|
||||
DB 48h ; dec ax
|
||||
DB 2eh
|
||||
mov [rdi], eax ; mov cs:[bx], ax
|
||||
DB 66h, 2eh, 0a1h ; mov eax, cs:[offset16]
|
||||
DW DSC_OFFSET + DSC_GDTPTR
|
||||
DB 2eh
|
||||
mov [rdi + 2], ax ; mov cs:[bx + 2], eax
|
||||
DB 66h, 2eh
|
||||
lgdt fword ptr [rdi] ; lgdt fword ptr cs:[bx]
|
||||
; Patch ProtectedMode Segment
|
||||
DB 0b8h ; mov ax, imm16
|
||||
DW PROTECT_MODE_CS ; set AX for segment directly
|
||||
DB 2eh
|
||||
mov [rdi - 2], eax ; mov cs:[bx - 2], ax
|
||||
; Patch ProtectedMode entry
|
||||
DB 66h, 0bfh ; mov edi, SMBASE
|
||||
gSmbase DD ?
|
||||
lea ax, [edi + (@ProtectedMode - _SmiEntryPoint) + 8000h]
|
||||
DB 2eh
|
||||
mov [rdi - 6], ax ; mov cs:[bx - 6], eax
|
||||
; Switch into @ProtectedMode
|
||||
mov rbx, cr0
|
||||
DB 66h
|
||||
and ebx, 9ffafff3h
|
||||
DB 66h
|
||||
or ebx, 00000023h
|
||||
|
||||
mov cr0, rbx
|
||||
DB 66h, 0eah
|
||||
DD ?
|
||||
DW ?
|
||||
|
||||
_GdtDesc FWORD ?
|
||||
@ProtectedMode:
|
||||
mov ax, PROTECT_MODE_DS
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
DB 0bch ; mov esp, imm32
|
||||
gSmiStack DD ?
|
||||
jmp ProtFlatMode
|
||||
|
||||
ProtFlatMode:
|
||||
DB 0b8h ; mov eax, offset gSmiCr3
|
||||
gSmiCr3 DD ?
|
||||
mov cr3, rax
|
||||
mov eax, 668h ; as cr4.PGE is not set here, refresh cr3
|
||||
mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
|
||||
; Load TSS
|
||||
sub esp, 8 ; reserve room in stack
|
||||
sgdt fword ptr [rsp]
|
||||
mov eax, [rsp + 2] ; eax = GDT base
|
||||
add esp, 8
|
||||
mov dl, 89h
|
||||
mov [rax + TSS_SEGMENT + 5], dl ; clear busy flag
|
||||
mov eax, TSS_SEGMENT
|
||||
ltr ax
|
||||
|
||||
; Switch into @LongMode
|
||||
push LONG_MODE_CS ; push cs hardcore here
|
||||
call Base ; push return address for retf later
|
||||
Base:
|
||||
add dword ptr [rsp], @LongMode - Base; offset for far retf, seg is the 1st arg
|
||||
mov ecx, 0c0000080h
|
||||
rdmsr
|
||||
or ah, 1
|
||||
wrmsr
|
||||
mov rbx, cr0
|
||||
or ebx, 080010000h ; enable paging + WP
|
||||
mov cr0, rbx
|
||||
retf
|
||||
@LongMode: ; long mode (64-bit code) starts here
|
||||
mov rax, offset gSmiHandlerIdtr
|
||||
lidt fword ptr [rax]
|
||||
lea ebx, [rdi + DSC_OFFSET]
|
||||
mov ax, [rbx + DSC_DS]
|
||||
mov ds, eax
|
||||
mov ax, [rbx + DSC_OTHERSEG]
|
||||
mov es, eax
|
||||
mov fs, eax
|
||||
mov gs, eax
|
||||
mov ax, [rbx + DSC_SS]
|
||||
mov ss, eax
|
||||
; jmp _SmiHandler ; instruction is not needed
|
||||
|
||||
_SmiHandler:
|
||||
; below step is needed, because STM does not run above code.
|
||||
; we have to run below code to set IDT/CR0/CR4
|
||||
mov rax, offset gSmiHandlerIdtr
|
||||
lidt fword ptr [rax]
|
||||
mov rax, cr0
|
||||
or eax, 00000022h
|
||||
or eax, 00010000h ; enable WP
|
||||
mov cr0, rax
|
||||
mov rax, cr4
|
||||
mov eax, 668h ; as cr4.PGE is not set here, refresh cr3
|
||||
mov cr4, rax ; in PreModifyMtrrs() to flush TLB.
|
||||
; STM init finish
|
||||
|
||||
mov rbx, [rsp] ; rbx <- CpuIndex
|
||||
|
||||
;
|
||||
; Save FP registers
|
||||
;
|
||||
sub rsp, 208h
|
||||
DB 48h ; FXSAVE64
|
||||
fxsave [rsp]
|
||||
|
||||
add rsp, -20h
|
||||
|
||||
mov rcx, rbx
|
||||
mov rax, CpuSmmDebugEntry
|
||||
call rax
|
||||
|
||||
mov rcx, rbx
|
||||
mov rax, SmiRendezvous ; rax <- absolute addr of SmiRedezvous
|
||||
call rax
|
||||
|
||||
mov rcx, rbx
|
||||
mov rax, CpuSmmDebugExit
|
||||
call rax
|
||||
|
||||
add rsp, 20h
|
||||
|
||||
;
|
||||
; Restore FP registers
|
||||
;
|
||||
DB 48h ; FXRSTOR64
|
||||
fxrstor [rsp]
|
||||
|
||||
rsm
|
||||
|
||||
gcSmiHandlerSize DW $ - _SmiEntryPoint
|
||||
|
||||
END
|
|
@ -0,0 +1,659 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2009 - 2016, Intel Corporation. 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.
|
||||
#
|
||||
# Module Name:
|
||||
#
|
||||
# SmiException.S
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
# Exception handlers used in SM mode
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
ASM_GLOBAL ASM_PFX(SmiPFHandler)
|
||||
ASM_GLOBAL ASM_PFX(gSmiMtrrs)
|
||||
ASM_GLOBAL ASM_PFX(gcSmiIdtr)
|
||||
ASM_GLOBAL ASM_PFX(gcSmiGdtr)
|
||||
ASM_GLOBAL ASM_PFX(gcPsd)
|
||||
|
||||
|
||||
ASM_GLOBAL ASM_PFX(SmmStmExceptionHandler)
|
||||
ASM_GLOBAL ASM_PFX(SmmStmSetup)
|
||||
ASM_GLOBAL ASM_PFX(SmmStmTeardown)
|
||||
|
||||
.data
|
||||
|
||||
NullSeg: .quad 0 # reserved by architecture
|
||||
CodeSeg32:
|
||||
.word -1 # LimitLow
|
||||
.word 0 # BaseLow
|
||||
.byte 0 # BaseMid
|
||||
.byte 0x9b
|
||||
.byte 0xcf # LimitHigh
|
||||
.byte 0 # BaseHigh
|
||||
ProtModeCodeSeg32:
|
||||
.word -1 # LimitLow
|
||||
.word 0 # BaseLow
|
||||
.byte 0 # BaseMid
|
||||
.byte 0x9b
|
||||
.byte 0xcf # LimitHigh
|
||||
.byte 0 # BaseHigh
|
||||
ProtModeSsSeg32:
|
||||
.word -1 # LimitLow
|
||||
.word 0 # BaseLow
|
||||
.byte 0 # BaseMid
|
||||
.byte 0x93
|
||||
.byte 0xcf # LimitHigh
|
||||
.byte 0 # BaseHigh
|
||||
DataSeg32:
|
||||
.word -1 # LimitLow
|
||||
.word 0 # BaseLow
|
||||
.byte 0 # BaseMid
|
||||
.byte 0x93
|
||||
.byte 0xcf # LimitHigh
|
||||
.byte 0 # BaseHigh
|
||||
CodeSeg16:
|
||||
.word -1
|
||||
.word 0
|
||||
.byte 0
|
||||
.byte 0x9b
|
||||
.byte 0x8f
|
||||
.byte 0
|
||||
DataSeg16:
|
||||
.word -1
|
||||
.word 0
|
||||
.byte 0
|
||||
.byte 0x93
|
||||
.byte 0x8f
|
||||
.byte 0
|
||||
CodeSeg64:
|
||||
.word -1 # LimitLow
|
||||
.word 0 # BaseLow
|
||||
.byte 0 # BaseMid
|
||||
.byte 0x9b
|
||||
.byte 0xaf # LimitHigh
|
||||
.byte 0 # BaseHigh
|
||||
# TSS Segment for X64 specially
|
||||
TssSeg:
|
||||
.word TSS_DESC_SIZE - 1 # LimitLow
|
||||
.word 0 # BaseLow
|
||||
.byte 0 # BaseMid
|
||||
.byte 0x89
|
||||
.byte 0x00 # LimitHigh
|
||||
.byte 0 # BaseHigh
|
||||
.long 0 # BaseUpper
|
||||
.long 0 # Reserved
|
||||
.equ GDT_SIZE, .- NullSeg
|
||||
|
||||
TssDescriptor:
|
||||
.space 104, 0
|
||||
.equ TSS_DESC_SIZE, .- TssDescriptor
|
||||
|
||||
#
|
||||
# This structure serves as a template for all processors.
|
||||
#
|
||||
ASM_PFX(gcPsd):
|
||||
.ascii "TXTPSSIG"
|
||||
.word PSD_SIZE
|
||||
.word 1 # Version
|
||||
.long 0 # LocalApicId
|
||||
.byte 0xF # Cr4Pse;Cr4Pae;Intel64Mode;ExecutionDisableOutsideSmrr
|
||||
.byte 0 # BIOS to STM
|
||||
.byte 0 # STM to BIOS
|
||||
.byte 0
|
||||
.word CODE_SEL
|
||||
.word DATA_SEL
|
||||
.word DATA_SEL
|
||||
.word DATA_SEL
|
||||
.word TR_SEL
|
||||
.word 0
|
||||
.quad 0 # SmmCr3
|
||||
.quad ASM_PFX(_OnStmSetup)
|
||||
.quad ASM_PFX(_OnStmTeardown)
|
||||
.quad 0 # SmmSmiHandlerRip - SMM guest entrypoint
|
||||
.quad 0 # SmmSmiHandlerRsp
|
||||
.quad NullSeg
|
||||
.long GDT_SIZE
|
||||
.long 0x80010100 # RequiredStmSmmRevId
|
||||
.quad ASM_PFX(_OnException)
|
||||
.quad 0 # ExceptionStack
|
||||
.quad DATA_SEL
|
||||
.quad 0x1F # ExceptionFilter
|
||||
.long 0
|
||||
.quad ASM_PFX(gSmiMtrrs)
|
||||
.quad 0 # BiosHwResourceRequirementsPtr
|
||||
.quad 0 # AcpiRsdp
|
||||
.byte 0 # PhysicalAddressBits
|
||||
.equ PSD_SIZE, . - ASM_PFX(gcPsd)
|
||||
|
||||
#
|
||||
# CODE & DATA segments for SMM runtime
|
||||
#
|
||||
.equ CODE_SEL, CodeSeg64 - NullSeg
|
||||
.equ DATA_SEL, DataSeg32 - NullSeg
|
||||
.equ TR_SEL, TssSeg - NullSeg
|
||||
.equ CODE32_SEL, CodeSeg32 - NullSeg
|
||||
|
||||
ASM_PFX(gcSmiGdtr):
|
||||
.word GDT_SIZE - 1
|
||||
.quad NullSeg
|
||||
|
||||
ASM_PFX(gcSmiIdtr):
|
||||
.word IDT_SIZE - 1
|
||||
.quad _SmiIDT
|
||||
|
||||
|
||||
#
|
||||
# Here is the IDT. There are 32 (not 255) entries in it since only processor
|
||||
# generated exceptions will be handled.
|
||||
#
|
||||
_SmiIDT:
|
||||
# The following segment repeats 32 times:
|
||||
# No. 1
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 2
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 3
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 4
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 5
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 6
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 7
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 8
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 9
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 10
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 11
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 12
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 13
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 14
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 15
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 16
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 17
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 18
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 19
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 20
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 21
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 22
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 23
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 24
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 25
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 26
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 27
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 28
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 29
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 30
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 31
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
# No. 32
|
||||
.word 0 # Offset 0:15
|
||||
.word CODE_SEL
|
||||
.byte 0 # Unused
|
||||
.byte 0x8e # Interrupt Gate, Present
|
||||
.word 0 # Offset 16:31
|
||||
.quad 0 # Offset 32:63
|
||||
|
||||
_SmiIDTEnd:
|
||||
|
||||
.equ IDT_SIZE, (_SmiIDTEnd - _SmiIDT)
|
||||
|
||||
.text
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# _SmiExceptionEntryPoints is the collection of exception entry points followed
|
||||
# by a common exception handler.
|
||||
#
|
||||
# Stack frame would be as follows as specified in IA32 manuals:
|
||||
# +---------------------+ <-- 16-byte aligned ensured by processor
|
||||
# + Old SS +
|
||||
# +---------------------+
|
||||
# + Old RSP +
|
||||
# +---------------------+
|
||||
# + RFlags +
|
||||
# +---------------------+
|
||||
# + CS +
|
||||
# +---------------------+
|
||||
# + RIP +
|
||||
# +---------------------+
|
||||
# + Error Code +
|
||||
# +---------------------+
|
||||
# + Vector Number +
|
||||
# +---------------------+
|
||||
# + RBP +
|
||||
# +---------------------+ <-- RBP, 16-byte aligned
|
||||
#
|
||||
# RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT
|
||||
#------------------------------------------------------------------------------
|
||||
ASM_GLOBAL ASM_PFX(PageFaultIdtHandlerSmmProfile)
|
||||
ASM_PFX(PageFaultIdtHandlerSmmProfile):
|
||||
pushq $0x0e # Page Fault
|
||||
.byte 0x40, 0xf6, 0xc4, 0x08 #test spl, 8
|
||||
jnz L1
|
||||
pushq (%rsp)
|
||||
movq $0, 8(%rsp)
|
||||
L1:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
|
||||
#
|
||||
# Since here the stack pointer is 16-byte aligned, so
|
||||
# EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
|
||||
# is 16-byte aligned
|
||||
#
|
||||
|
||||
## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
pushq %r15
|
||||
pushq %r14
|
||||
pushq %r13
|
||||
pushq %r12
|
||||
pushq %r11
|
||||
pushq %r10
|
||||
pushq %r9
|
||||
pushq %r8
|
||||
pushq %rax
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
pushq %rbx
|
||||
pushq 48(%rbp) # RSP
|
||||
pushq (%rbp) # RBP
|
||||
pushq %rsi
|
||||
pushq %rdi
|
||||
|
||||
## UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
|
||||
movzwq 56(%rbp), %rax
|
||||
pushq %rax # for ss
|
||||
movzwq 32(%rbp), %rax
|
||||
pushq %rax # for cs
|
||||
movq %ds, %rax
|
||||
pushq %rax
|
||||
movq %es, %rax
|
||||
pushq %rax
|
||||
movq %fs, %rax
|
||||
pushq %rax
|
||||
movq %gs, %rax
|
||||
pushq %rax
|
||||
|
||||
## UINT64 Rip;
|
||||
pushq 24(%rbp)
|
||||
|
||||
## UINT64 Gdtr[2], Idtr[2];
|
||||
subq $16, %rsp
|
||||
sidt (%rsp)
|
||||
subq $16, %rsp
|
||||
sgdt (%rsp)
|
||||
|
||||
## UINT64 Ldtr, Tr;
|
||||
xorq %rax, %rax
|
||||
strw %ax
|
||||
pushq %rax
|
||||
sldtw %ax
|
||||
pushq %rax
|
||||
|
||||
## UINT64 RFlags;
|
||||
pushq 40(%rbp)
|
||||
|
||||
## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
|
||||
movq %cr8, %rax
|
||||
pushq %rax
|
||||
movq %cr4, %rax
|
||||
orq $0x208, %rax
|
||||
movq %rax, %cr4
|
||||
pushq %rax
|
||||
movq %cr3, %rax
|
||||
pushq %rax
|
||||
movq %cr2, %rax
|
||||
pushq %rax
|
||||
xorq %rax, %rax
|
||||
pushq %rax
|
||||
movq %cr0, %rax
|
||||
pushq %rax
|
||||
|
||||
## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
movq %dr7, %rax
|
||||
pushq %rax
|
||||
movq %dr6, %rax
|
||||
pushq %rax
|
||||
movq %dr3, %rax
|
||||
pushq %rax
|
||||
movq %dr2, %rax
|
||||
pushq %rax
|
||||
movq %dr1, %rax
|
||||
pushq %rax
|
||||
movq %dr0, %rax
|
||||
pushq %rax
|
||||
|
||||
## FX_SAVE_STATE_X64 FxSaveState;
|
||||
|
||||
subq $512, %rsp
|
||||
movq %rsp, %rdi
|
||||
.byte 0xf, 0xae, 0x7 # fxsave [rdi]
|
||||
|
||||
# UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
|
||||
cld
|
||||
|
||||
## UINT32 ExceptionData;
|
||||
pushq 16(%rbp)
|
||||
|
||||
## call into exception handler
|
||||
movq 8(%rbp), %rcx
|
||||
movabsq $ASM_PFX(SmiPFHandler), %rax
|
||||
|
||||
## Prepare parameter and call
|
||||
movq %rsp, %rdx
|
||||
#
|
||||
# Per X64 calling convention, allocate maximum parameter stack space
|
||||
# and make sure RSP is 16-byte aligned
|
||||
#
|
||||
subq $4 * 8 + 8, %rsp
|
||||
call *%rax
|
||||
addq $4 * 8 + 8, %rsp
|
||||
jmp L5
|
||||
|
||||
L5:
|
||||
## UINT64 ExceptionData;
|
||||
addq $8, %rsp
|
||||
|
||||
## FX_SAVE_STATE_X64 FxSaveState;
|
||||
|
||||
movq %rsp, %rsi
|
||||
.byte 0xf, 0xae, 0xe # fxrstor [rsi]
|
||||
addq $512, %rsp
|
||||
|
||||
## UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
## Skip restoration of DRx registers to support debuggers
|
||||
## that set breakpoints in interrupt/exception context
|
||||
addq $8 * 6, %rsp
|
||||
|
||||
## UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
|
||||
popq %rax
|
||||
movq %rax, %cr0
|
||||
addq $8, %rsp # not for Cr1
|
||||
popq %rax
|
||||
movq %rax, %cr2
|
||||
popq %rax
|
||||
movq %rax, %cr3
|
||||
popq %rax
|
||||
movq %rax, %cr4
|
||||
popq %rax
|
||||
movq %rax, %cr8
|
||||
|
||||
## UINT64 RFlags;
|
||||
popq 40(%rbp)
|
||||
|
||||
## UINT64 Ldtr, Tr;
|
||||
## UINT64 Gdtr[2], Idtr[2];
|
||||
## Best not let anyone mess with these particular registers...
|
||||
addq $48, %rsp
|
||||
|
||||
## UINT64 Rip;
|
||||
popq 24(%rbp)
|
||||
|
||||
## UINT64 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
popq %rax
|
||||
# mov gs, rax ; not for gs
|
||||
popq %rax
|
||||
# mov fs, rax ; not for fs
|
||||
# (X64 will not use fs and gs, so we do not restore it)
|
||||
popq %rax
|
||||
movq %rax, %es
|
||||
popq %rax
|
||||
movq %rax, %ds
|
||||
popq 32(%rbp) # for cs
|
||||
popq 56(%rbp) # for ss
|
||||
|
||||
## UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
## UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
popq %rdi
|
||||
popq %rsi
|
||||
addq $8, %rsp # not for rbp
|
||||
popq 48(%rbp) # for rsp
|
||||
popq %rbx
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rax
|
||||
popq %r8
|
||||
popq %r9
|
||||
popq %r10
|
||||
popq %r11
|
||||
popq %r12
|
||||
popq %r13
|
||||
popq %r14
|
||||
popq %r15
|
||||
|
||||
movq %rbp, %rsp
|
||||
|
||||
# Enable TF bit after page fault handler runs
|
||||
btsl $8, 40(%rsp) #RFLAGS
|
||||
|
||||
popq %rbp
|
||||
addq $16, %rsp # skip INT# & ErrCode
|
||||
iretq
|
||||
|
||||
ASM_GLOBAL ASM_PFX(InitializeIDTSmmStackGuard)
|
||||
ASM_PFX(InitializeIDTSmmStackGuard):
|
||||
# If SMM Stack Guard feature is enabled, set the IST field of
|
||||
# the interrupt gate for Page Fault Exception to be 1
|
||||
#
|
||||
movabsq $_SmiIDT + 14 * 16, %rax
|
||||
movb $1, 4(%rax)
|
||||
ret
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# SMM Exception handlers
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
ASM_GLOBAL ASM_PFX(_OnException)
|
||||
ASM_PFX(_OnException):
|
||||
movq %rsp, %rcx
|
||||
subq $0x28, %rsp
|
||||
call ASM_PFX(SmmStmExceptionHandler)
|
||||
addq $0x28, %rsp
|
||||
movl %eax, %ebx
|
||||
movl $4, %eax
|
||||
.byte 0xf, 0x1, 0xc1 # VMCALL
|
||||
jmp .
|
||||
|
||||
ASM_GLOBAL ASM_PFX(_OnStmSetup)
|
||||
ASM_PFX(_OnStmSetup):
|
||||
subq $0x28, %rsp
|
||||
call ASM_PFX(SmmStmSetup)
|
||||
addq 0x28, %rsp
|
||||
rsm
|
||||
|
||||
ASM_GLOBAL ASM_PFX(_OnStmTeardown)
|
||||
ASM_PFX(_OnStmTeardown):
|
||||
subq $0x28, %rsp
|
||||
call ASM_PFX(SmmStmTeardown)
|
||||
addq $0x28, %rsp
|
||||
rsm
|
|
@ -0,0 +1,460 @@
|
|||
;------------------------------------------------------------------------------ ;
|
||||
; Copyright (c) 2009 - 2016, Intel Corporation. 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.
|
||||
;
|
||||
; Module Name:
|
||||
;
|
||||
; SmiException.asm
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; Exception handlers used in SM mode
|
||||
;
|
||||
;-------------------------------------------------------------------------------
|
||||
|
||||
EXTERNDEF SmiPFHandler:PROC
|
||||
EXTERNDEF gSmiMtrrs:QWORD
|
||||
EXTERNDEF gcSmiIdtr:FWORD
|
||||
EXTERNDEF gcSmiGdtr:FWORD
|
||||
EXTERNDEF gcPsd:BYTE
|
||||
|
||||
SmmStmExceptionHandler PROTO
|
||||
SmmStmSetup PROTO
|
||||
SmmStmTeardown PROTO
|
||||
|
||||
.const
|
||||
|
||||
NullSeg DQ 0 ; reserved by architecture
|
||||
CodeSeg32 LABEL QWORD
|
||||
DW -1 ; LimitLow
|
||||
DW 0 ; BaseLow
|
||||
DB 0 ; BaseMid
|
||||
DB 9bh
|
||||
DB 0cfh ; LimitHigh
|
||||
DB 0 ; BaseHigh
|
||||
ProtModeCodeSeg32 LABEL QWORD
|
||||
DW -1 ; LimitLow
|
||||
DW 0 ; BaseLow
|
||||
DB 0 ; BaseMid
|
||||
DB 9bh
|
||||
DB 0cfh ; LimitHigh
|
||||
DB 0 ; BaseHigh
|
||||
ProtModeSsSeg32 LABEL QWORD
|
||||
DW -1 ; LimitLow
|
||||
DW 0 ; BaseLow
|
||||
DB 0 ; BaseMid
|
||||
DB 93h
|
||||
DB 0cfh ; LimitHigh
|
||||
DB 0 ; BaseHigh
|
||||
DataSeg32 LABEL QWORD
|
||||
DW -1 ; LimitLow
|
||||
DW 0 ; BaseLow
|
||||
DB 0 ; BaseMid
|
||||
DB 93h
|
||||
DB 0cfh ; LimitHigh
|
||||
DB 0 ; BaseHigh
|
||||
CodeSeg16 LABEL QWORD
|
||||
DW -1
|
||||
DW 0
|
||||
DB 0
|
||||
DB 9bh
|
||||
DB 8fh
|
||||
DB 0
|
||||
DataSeg16 LABEL QWORD
|
||||
DW -1
|
||||
DW 0
|
||||
DB 0
|
||||
DB 93h
|
||||
DB 8fh
|
||||
DB 0
|
||||
CodeSeg64 LABEL QWORD
|
||||
DW -1 ; LimitLow
|
||||
DW 0 ; BaseLow
|
||||
DB 0 ; BaseMid
|
||||
DB 9bh
|
||||
DB 0afh ; LimitHigh
|
||||
DB 0 ; BaseHigh
|
||||
; TSS Segment for X64 specially
|
||||
TssSeg LABEL QWORD
|
||||
DW TSS_DESC_SIZE - 1 ; LimitLow
|
||||
DW 0 ; BaseLow
|
||||
DB 0 ; BaseMid
|
||||
DB 89h
|
||||
DB 00h ; LimitHigh
|
||||
DB 0 ; BaseHigh
|
||||
DD 0 ; BaseUpper
|
||||
DD 0 ; Reserved
|
||||
GDT_SIZE = $ - offset NullSeg
|
||||
|
||||
; Create TSS Descriptor just after GDT
|
||||
TssDescriptor LABEL BYTE
|
||||
DD 0 ; Reserved
|
||||
DQ 0 ; RSP0
|
||||
DQ 0 ; RSP1
|
||||
DQ 0 ; RSP2
|
||||
DD 0 ; Reserved
|
||||
DD 0 ; Reserved
|
||||
DQ 0 ; IST1
|
||||
DQ 0 ; IST2
|
||||
DQ 0 ; IST3
|
||||
DQ 0 ; IST4
|
||||
DQ 0 ; IST5
|
||||
DQ 0 ; IST6
|
||||
DQ 0 ; IST7
|
||||
DD 0 ; Reserved
|
||||
DD 0 ; Reserved
|
||||
DW 0 ; Reserved
|
||||
DW 0 ; I/O Map Base Address
|
||||
TSS_DESC_SIZE = $ - offset TssDescriptor
|
||||
|
||||
;
|
||||
; This structure serves as a template for all processors.
|
||||
;
|
||||
gcPsd LABEL BYTE
|
||||
DB 'TXTPSSIG'
|
||||
DW PSD_SIZE
|
||||
DW 1 ; Version
|
||||
DD 0 ; LocalApicId
|
||||
DB 0Fh ; Cr4Pse;Cr4Pae;Intel64Mode;ExecutionDisableOutsideSmrr
|
||||
DB 0 ; BIOS to STM
|
||||
DB 0 ; STM to BIOS
|
||||
DB 0
|
||||
DW CODE_SEL
|
||||
DW DATA_SEL
|
||||
DW DATA_SEL
|
||||
DW DATA_SEL
|
||||
DW TR_SEL
|
||||
DW 0
|
||||
DQ 0 ; SmmCr3
|
||||
DQ _OnStmSetup
|
||||
DQ _OnStmTeardown
|
||||
DQ 0 ; SmmSmiHandlerRip - SMM guest entrypoint
|
||||
DQ 0 ; SmmSmiHandlerRsp
|
||||
DQ offset NullSeg
|
||||
DD GDT_SIZE
|
||||
DD 80010100h ; RequiredStmSmmRevId
|
||||
DQ _OnException
|
||||
DQ 0 ; ExceptionStack
|
||||
DW DATA_SEL
|
||||
DW 01Fh ; ExceptionFilter
|
||||
DD 0
|
||||
DQ offset gSmiMtrrs
|
||||
DQ 0 ; BiosHwResourceRequirementsPtr
|
||||
DQ 0 ; AcpiRsdp
|
||||
DB 0 ; PhysicalAddressBits
|
||||
PSD_SIZE = $ - offset gcPsd
|
||||
|
||||
;
|
||||
; CODE & DATA segments for SMM runtime
|
||||
;
|
||||
CODE_SEL = offset CodeSeg64 - offset NullSeg
|
||||
DATA_SEL = offset DataSeg32 - offset NullSeg
|
||||
TR_SEL = offset TssSeg - offset NullSeg
|
||||
CODE32_SEL = offset CodeSeg32 - offset NullSeg
|
||||
|
||||
gcSmiGdtr LABEL FWORD
|
||||
DW GDT_SIZE - 1
|
||||
DQ offset NullSeg
|
||||
|
||||
gcSmiIdtr LABEL FWORD
|
||||
DW IDT_SIZE - 1
|
||||
DQ offset _SmiIDT
|
||||
|
||||
.data
|
||||
|
||||
;
|
||||
; Here is the IDT. There are 32 (not 255) entries in it since only processor
|
||||
; generated exceptions will be handled.
|
||||
;
|
||||
_SmiIDT:
|
||||
REPEAT 32
|
||||
DW 0 ; Offset 0:15
|
||||
DW CODE_SEL ; Segment selector
|
||||
DB 0 ; Unused
|
||||
DB 8eh ; Interrupt Gate, Present
|
||||
DW 0 ; Offset 16:31
|
||||
DQ 0 ; Offset 32:63
|
||||
ENDM
|
||||
_SmiIDTEnd:
|
||||
|
||||
IDT_SIZE = (offset _SmiIDTEnd - offset _SmiIDT)
|
||||
|
||||
.code
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; _SmiExceptionEntryPoints is the collection of exception entry points followed
|
||||
; by a common exception handler.
|
||||
;
|
||||
; Stack frame would be as follows as specified in IA32 manuals:
|
||||
;
|
||||
; +---------------------+ <-- 16-byte aligned ensured by processor
|
||||
; + Old SS +
|
||||
; +---------------------+
|
||||
; + Old RSP +
|
||||
; +---------------------+
|
||||
; + RFlags +
|
||||
; +---------------------+
|
||||
; + CS +
|
||||
; +---------------------+
|
||||
; + RIP +
|
||||
; +---------------------+
|
||||
; + Error Code +
|
||||
; +---------------------+
|
||||
; + Vector Number +
|
||||
; +---------------------+
|
||||
; + RBP +
|
||||
; +---------------------+ <-- RBP, 16-byte aligned
|
||||
;
|
||||
; RSP set to odd multiple of 8 at @CommonEntryPoint means ErrCode PRESENT
|
||||
;------------------------------------------------------------------------------
|
||||
PageFaultIdtHandlerSmmProfile PROC
|
||||
push 0eh ; Page Fault
|
||||
test spl, 8 ; odd multiple of 8 => ErrCode present
|
||||
jnz @F
|
||||
push [rsp] ; duplicate INT# if no ErrCode
|
||||
mov qword ptr [rsp + 8], 0
|
||||
@@:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
;
|
||||
; Since here the stack pointer is 16-byte aligned, so
|
||||
; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
|
||||
; is 16-byte aligned
|
||||
;
|
||||
|
||||
;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
push r15
|
||||
push r14
|
||||
push r13
|
||||
push r12
|
||||
push r11
|
||||
push r10
|
||||
push r9
|
||||
push r8
|
||||
push rax
|
||||
push rcx
|
||||
push rdx
|
||||
push rbx
|
||||
push qword ptr [rbp + 48] ; RSP
|
||||
push qword ptr [rbp] ; RBP
|
||||
push rsi
|
||||
push rdi
|
||||
|
||||
;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
|
||||
movzx rax, word ptr [rbp + 56]
|
||||
push rax ; for ss
|
||||
movzx rax, word ptr [rbp + 32]
|
||||
push rax ; for cs
|
||||
mov rax, ds
|
||||
push rax
|
||||
mov rax, es
|
||||
push rax
|
||||
mov rax, fs
|
||||
push rax
|
||||
mov rax, gs
|
||||
push rax
|
||||
|
||||
;; UINT64 Rip;
|
||||
push qword ptr [rbp + 24]
|
||||
|
||||
;; UINT64 Gdtr[2], Idtr[2];
|
||||
sub rsp, 16
|
||||
sidt fword ptr [rsp]
|
||||
sub rsp, 16
|
||||
sgdt fword ptr [rsp]
|
||||
|
||||
;; UINT64 Ldtr, Tr;
|
||||
xor rax, rax
|
||||
str ax
|
||||
push rax
|
||||
sldt ax
|
||||
push rax
|
||||
|
||||
;; UINT64 RFlags;
|
||||
push qword ptr [rbp + 40]
|
||||
|
||||
;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
|
||||
mov rax, cr8
|
||||
push rax
|
||||
mov rax, cr4
|
||||
or rax, 208h
|
||||
mov cr4, rax
|
||||
push rax
|
||||
mov rax, cr3
|
||||
push rax
|
||||
mov rax, cr2
|
||||
push rax
|
||||
xor rax, rax
|
||||
push rax
|
||||
mov rax, cr0
|
||||
push rax
|
||||
|
||||
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
mov rax, dr7
|
||||
push rax
|
||||
mov rax, dr6
|
||||
push rax
|
||||
mov rax, dr3
|
||||
push rax
|
||||
mov rax, dr2
|
||||
push rax
|
||||
mov rax, dr1
|
||||
push rax
|
||||
mov rax, dr0
|
||||
push rax
|
||||
|
||||
;; FX_SAVE_STATE_X64 FxSaveState;
|
||||
|
||||
sub rsp, 512
|
||||
mov rdi, rsp
|
||||
db 0fh, 0aeh, 00000111y ;fxsave [rdi]
|
||||
|
||||
; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
|
||||
cld
|
||||
|
||||
;; UINT32 ExceptionData;
|
||||
push qword ptr [rbp + 16]
|
||||
|
||||
;; call into exception handler
|
||||
mov rcx, [rbp + 8]
|
||||
mov rax, SmiPFHandler
|
||||
|
||||
;; Prepare parameter and call
|
||||
mov rdx, rsp
|
||||
;
|
||||
; Per X64 calling convention, allocate maximum parameter stack space
|
||||
; and make sure RSP is 16-byte aligned
|
||||
;
|
||||
sub rsp, 4 * 8 + 8
|
||||
call rax
|
||||
add rsp, 4 * 8 + 8
|
||||
jmp @F
|
||||
|
||||
@@:
|
||||
;; UINT64 ExceptionData;
|
||||
add rsp, 8
|
||||
|
||||
;; FX_SAVE_STATE_X64 FxSaveState;
|
||||
|
||||
mov rsi, rsp
|
||||
db 0fh, 0aeh, 00001110y ; fxrstor [rsi]
|
||||
add rsp, 512
|
||||
|
||||
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
;; Skip restoration of DRx registers to support debuggers
|
||||
;; that set breakpoints in interrupt/exception context
|
||||
add rsp, 8 * 6
|
||||
|
||||
;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
|
||||
pop rax
|
||||
mov cr0, rax
|
||||
add rsp, 8 ; not for Cr1
|
||||
pop rax
|
||||
mov cr2, rax
|
||||
pop rax
|
||||
mov cr3, rax
|
||||
pop rax
|
||||
mov cr4, rax
|
||||
pop rax
|
||||
mov cr8, rax
|
||||
|
||||
;; UINT64 RFlags;
|
||||
pop qword ptr [rbp + 40]
|
||||
|
||||
;; UINT64 Ldtr, Tr;
|
||||
;; UINT64 Gdtr[2], Idtr[2];
|
||||
;; Best not let anyone mess with these particular registers...
|
||||
add rsp, 48
|
||||
|
||||
;; UINT64 Rip;
|
||||
pop qword ptr [rbp + 24]
|
||||
|
||||
;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
pop rax
|
||||
; mov gs, rax ; not for gs
|
||||
pop rax
|
||||
; mov fs, rax ; not for fs
|
||||
; (X64 will not use fs and gs, so we do not restore it)
|
||||
pop rax
|
||||
mov es, rax
|
||||
pop rax
|
||||
mov ds, rax
|
||||
pop qword ptr [rbp + 32] ; for cs
|
||||
pop qword ptr [rbp + 56] ; for ss
|
||||
|
||||
;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
pop rdi
|
||||
pop rsi
|
||||
add rsp, 8 ; not for rbp
|
||||
pop qword ptr [rbp + 48] ; for rsp
|
||||
pop rbx
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rax
|
||||
pop r8
|
||||
pop r9
|
||||
pop r10
|
||||
pop r11
|
||||
pop r12
|
||||
pop r13
|
||||
pop r14
|
||||
pop r15
|
||||
|
||||
mov rsp, rbp
|
||||
|
||||
; Enable TF bit after page fault handler runs
|
||||
bts dword ptr [rsp + 40], 8 ;RFLAGS
|
||||
|
||||
pop rbp
|
||||
add rsp, 16 ; skip INT# & ErrCode
|
||||
iretq
|
||||
PageFaultIdtHandlerSmmProfile ENDP
|
||||
|
||||
InitializeIDTSmmStackGuard PROC
|
||||
;
|
||||
; If SMM Stack Guard feature is enabled, set the IST field of
|
||||
; the interrupt gate for Page Fault Exception to be 1
|
||||
;
|
||||
lea rax, _SmiIDT + 14 * 16
|
||||
mov byte ptr [rax + 4], 1
|
||||
ret
|
||||
InitializeIDTSmmStackGuard ENDP
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; SMM Exception handlers
|
||||
;------------------------------------------------------------------------------
|
||||
_OnException PROC
|
||||
mov rcx, rsp
|
||||
add rsp, -28h
|
||||
call SmmStmExceptionHandler
|
||||
add rsp, 28h
|
||||
mov ebx, eax
|
||||
mov eax, 4
|
||||
DB 0fh, 01h, 0c1h ; VMCALL
|
||||
jmp $
|
||||
_OnException ENDP
|
||||
|
||||
_OnStmSetup PROC
|
||||
add rsp, -28h
|
||||
call SmmStmSetup
|
||||
add rsp, 28h
|
||||
rsm
|
||||
_OnStmSetup ENDP
|
||||
|
||||
_OnStmTeardown PROC
|
||||
add rsp, -28h
|
||||
call SmmStmTeardown
|
||||
add rsp, 28h
|
||||
rsm
|
||||
_OnStmTeardown ENDP
|
||||
|
||||
END
|
|
@ -0,0 +1,70 @@
|
|||
/** @file
|
||||
SMM CPU misc functions for x64 arch specific.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "PiSmmCpuDxeSmm.h"
|
||||
|
||||
/**
|
||||
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
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
IA32_SEGMENT_DESCRIPTOR *GdtDescriptor;
|
||||
UINTN TssBase;
|
||||
UINTN GdtTssTableSize;
|
||||
UINT8 *GdtTssTables;
|
||||
UINTN GdtTableStepSize;
|
||||
|
||||
//
|
||||
// For X64 SMM, we allocate separate GDT/TSS for each CPUs to avoid TSS load contention
|
||||
// on each SMI entry.
|
||||
//
|
||||
GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE + 7) & ~7; // 8 bytes aligned
|
||||
GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));
|
||||
ASSERT (GdtTssTables != NULL);
|
||||
GdtTableStepSize = GdtTssTableSize;
|
||||
|
||||
for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; Index++) {
|
||||
CopyMem (GdtTssTables + GdtTableStepSize * Index, (VOID*)(UINTN)gcSmiGdtr.Base, gcSmiGdtr.Limit + 1 + TSS_SIZE);
|
||||
|
||||
//
|
||||
// Fixup TSS descriptors
|
||||
//
|
||||
TssBase = (UINTN)(GdtTssTables + GdtTableStepSize * Index + gcSmiGdtr.Limit + 1);
|
||||
GdtDescriptor = (IA32_SEGMENT_DESCRIPTOR *)(TssBase) - 2;
|
||||
GdtDescriptor->Bits.BaseLow = (UINT16)(UINTN)TssBase;
|
||||
GdtDescriptor->Bits.BaseMid = (UINT8)((UINTN)TssBase >> 16);
|
||||
GdtDescriptor->Bits.BaseHigh = (UINT8)((UINTN)TssBase >> 24);
|
||||
|
||||
if (FeaturePcdGet (PcdCpuSmmStackGuard)) {
|
||||
//
|
||||
// Setup top of known good stack as IST1 for each processor.
|
||||
//
|
||||
*(UINTN *)(TssBase + TSS_X64_IST1_OFFSET) = (mSmmStackArrayBase + EFI_PAGE_SIZE + Index * mSmmStackSize);
|
||||
}
|
||||
}
|
||||
|
||||
*GdtStepSize = GdtTableStepSize;
|
||||
return GdtTssTables;
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (c) 2009 - 2015, Intel Corporation. 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.
|
||||
#
|
||||
# Module Name:
|
||||
#
|
||||
# SmmInit.S
|
||||
#
|
||||
# Abstract:
|
||||
#
|
||||
# Functions for relocating SMBASE's for all processors
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
ASM_GLOBAL ASM_PFX(gSmmCr0)
|
||||
ASM_GLOBAL ASM_PFX(gSmmCr3)
|
||||
ASM_GLOBAL ASM_PFX(gSmmCr4)
|
||||
ASM_GLOBAL ASM_PFX(gSmmJmpAddr)
|
||||
ASM_GLOBAL ASM_PFX(gcSmmInitTemplate)
|
||||
ASM_GLOBAL ASM_PFX(gcSmmInitSize)
|
||||
ASM_GLOBAL ASM_PFX(mRebasedFlagAddr32)
|
||||
ASM_GLOBAL ASM_PFX(SmmRelocationSemaphoreComplete)
|
||||
ASM_GLOBAL ASM_PFX(SmmRelocationSemaphoreComplete32)
|
||||
ASM_GLOBAL ASM_PFX(mSmmRelocationOriginalAddressPtr32)
|
||||
ASM_GLOBAL ASM_PFX(gSmmInitStack)
|
||||
ASM_GLOBAL ASM_PFX(gcSmiInitGdtr)
|
||||
|
||||
|
||||
.text
|
||||
|
||||
ASM_PFX(gcSmiInitGdtr):
|
||||
.word 0
|
||||
.quad 0
|
||||
|
||||
SmmStartup:
|
||||
.byte 0x66,0xb8 # mov eax, imm32
|
||||
ASM_PFX(gSmmCr3): .space 4
|
||||
movq %rax, %cr3
|
||||
.byte 0x66,0x2e
|
||||
lgdt (ASM_PFX(gcSmiInitGdtr) - SmmStartup)(%ebp)
|
||||
.byte 0x66,0xb8 # mov eax, imm32
|
||||
ASM_PFX(gSmmCr4): .space 4
|
||||
orb $2, %ah # enable XMM registers access
|
||||
movq %rax, %cr4
|
||||
.byte 0x66
|
||||
movl $0xc0000080,%ecx # IA32_EFER MSR
|
||||
rdmsr
|
||||
orb $1,%ah # set LME bit
|
||||
wrmsr
|
||||
.byte 0x66,0xb8 # mov eax, imm32
|
||||
ASM_PFX(gSmmCr0): .space 4
|
||||
movq %rax, %cr0
|
||||
.byte 0x66,0xea # far jmp to long mode
|
||||
ASM_PFX(gSmmJmpAddr): .quad LongMode
|
||||
LongMode: # long-mode starts here
|
||||
.byte 0x48,0xbc # mov rsp, imm64
|
||||
ASM_PFX(gSmmInitStack): .space 8
|
||||
andw $0xfff0, %sp # make sure RSP is 16-byte aligned
|
||||
#
|
||||
# Accoring to X64 calling convention, XMM0~5 are volatile, we need to save
|
||||
# them before calling C-function.
|
||||
#
|
||||
subq $0x60, %rsp
|
||||
movdqa %xmm0, 0x0(%rsp)
|
||||
movdqa %xmm1, 0x10(%rsp)
|
||||
movdqa %xmm2, 0x20(%rsp)
|
||||
movdqa %xmm3, 0x30(%rsp)
|
||||
movdqa %xmm4, 0x40(%rsp)
|
||||
movdqa %xmm5, 0x50(%rsp)
|
||||
|
||||
|
||||
addq $-0x20, %rsp
|
||||
call ASM_PFX(SmmInitHandler)
|
||||
addq $0x20, %rsp
|
||||
#
|
||||
# Restore XMM0~5 after calling C-function.
|
||||
#
|
||||
movdqa 0x0(%rsp), %xmm0
|
||||
movdqa 0x10(%rsp), %xmm1
|
||||
movdqa 0x20(%rsp), %xmm2
|
||||
movdqa 0x30(%rsp), %xmm3
|
||||
movdqa 0x40(%rsp), %xmm4
|
||||
movdqa 0x50(%rsp), %xmm5
|
||||
|
||||
rsm
|
||||
|
||||
ASM_PFX(gcSmmInitTemplate):
|
||||
|
||||
_SmmInitTemplate:
|
||||
.byte 0x66,0x2e,0x8b,0x2e # mov ebp, cs:[@F]
|
||||
.word L1 - _SmmInitTemplate + 0x8000
|
||||
.byte 0x66, 0x81, 0xed, 0, 0, 3, 0 # sub ebp, 0x30000
|
||||
jmp *%bp # jmp ebp actually
|
||||
L1:
|
||||
.quad SmmStartup
|
||||
|
||||
ASM_PFX(gcSmmInitSize): .word . - ASM_PFX(gcSmmInitTemplate)
|
||||
|
||||
ASM_PFX(SmmRelocationSemaphoreComplete):
|
||||
# Create a simple stack frame to store RAX and the original RSM location
|
||||
pushq %rax # Used to store return address
|
||||
pushq %rax
|
||||
|
||||
# Load the original RSM location onto stack
|
||||
movabsq $ASM_PFX(mSmmRelocationOriginalAddress), %rax
|
||||
movq (%rax), %rax
|
||||
movq %rax, 0x08(%rsp)
|
||||
|
||||
# Update rebase flag
|
||||
movabsq $ASM_PFX(mRebasedFlag), %rax
|
||||
movq (%rax), %rax
|
||||
movb $1, (%rax)
|
||||
|
||||
#restore RAX and return to original RSM location
|
||||
popq %rax
|
||||
retq
|
||||
|
||||
#
|
||||
# Semaphore code running in 32-bit mode
|
||||
#
|
||||
ASM_PFX(SmmRelocationSemaphoreComplete32):
|
||||
#
|
||||
# movb $1, ()
|
||||
#
|
||||
.byte 0xc6, 0x05
|
||||
ASM_PFX(mRebasedFlagAddr32):
|
||||
.long 0
|
||||
.byte 1
|
||||
#
|
||||
# jmpd ()
|
||||
#
|
||||
.byte 0xff, 0x25
|
||||
ASM_PFX(mSmmRelocationOriginalAddressPtr32):
|
||||
.long 0
|
|
@ -0,0 +1,132 @@
|
|||
;------------------------------------------------------------------------------ ;
|
||||
; Copyright (c) 2009 - 2015, Intel Corporation. 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.
|
||||
;
|
||||
; Module Name:
|
||||
;
|
||||
; SmmInit.Asm
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; Functions for relocating SMBASE's for all processors
|
||||
;
|
||||
;-------------------------------------------------------------------------------
|
||||
|
||||
EXTERNDEF SmmInitHandler:PROC
|
||||
EXTERNDEF gSmmCr0:DWORD
|
||||
EXTERNDEF gSmmCr3:DWORD
|
||||
EXTERNDEF gSmmCr4:DWORD
|
||||
EXTERNDEF gSmmJmpAddr:QWORD
|
||||
EXTERNDEF gcSmmInitTemplate:BYTE
|
||||
EXTERNDEF gcSmmInitSize:WORD
|
||||
EXTERNDEF mRebasedFlag:PTR BYTE
|
||||
EXTERNDEF mSmmRelocationOriginalAddress:QWORD
|
||||
EXTERNDEF mRebasedFlagAddr32:DWORD
|
||||
EXTERNDEF mSmmRelocationOriginalAddressPtr32:DWORD
|
||||
EXTERNDEF gSmmInitStack:QWORD
|
||||
EXTERNDEF gcSmiInitGdtr:FWORD
|
||||
|
||||
.code
|
||||
|
||||
gcSmiInitGdtr LABEL FWORD
|
||||
DW 0
|
||||
DQ 0
|
||||
|
||||
SmmStartup PROC
|
||||
DB 66h, 0b8h ; mov eax, imm32
|
||||
gSmmCr3 DD ?
|
||||
mov cr3, rax
|
||||
DB 66h, 2eh
|
||||
lgdt fword ptr [ebp + (offset gcSmiInitGdtr - SmmStartup)]
|
||||
DB 66h, 0b8h ; mov eax, imm32
|
||||
gSmmCr4 DD ?
|
||||
or ah, 2 ; enable XMM registers access
|
||||
mov cr4, rax
|
||||
DB 66h
|
||||
mov ecx, 0c0000080h ; IA32_EFER MSR
|
||||
rdmsr
|
||||
or ah, 1 ; set LME bit
|
||||
wrmsr
|
||||
DB 66h, 0b8h ; mov eax, imm32
|
||||
gSmmCr0 DD ?
|
||||
mov cr0, rax ; enable protected mode & paging
|
||||
DB 66h, 0eah ; far jmp to long mode
|
||||
gSmmJmpAddr DQ @LongMode
|
||||
@LongMode: ; long-mode starts here
|
||||
DB 48h, 0bch ; mov rsp, imm64
|
||||
gSmmInitStack DQ ?
|
||||
and sp, 0fff0h ; make sure RSP is 16-byte aligned
|
||||
;
|
||||
; Accoring to X64 calling convention, XMM0~5 are volatile, we need to save
|
||||
; them before calling C-function.
|
||||
;
|
||||
sub rsp, 60h
|
||||
movdqa [rsp], xmm0
|
||||
movdqa [rsp + 10h], xmm1
|
||||
movdqa [rsp + 20h], xmm2
|
||||
movdqa [rsp + 30h], xmm3
|
||||
movdqa [rsp + 40h], xmm4
|
||||
movdqa [rsp + 50h], xmm5
|
||||
|
||||
add rsp, -20h
|
||||
call SmmInitHandler
|
||||
add rsp, 20h
|
||||
|
||||
;
|
||||
; Restore XMM0~5 after calling C-function.
|
||||
;
|
||||
movdqa xmm0, [rsp]
|
||||
movdqa xmm1, [rsp + 10h]
|
||||
movdqa xmm2, [rsp + 20h]
|
||||
movdqa xmm3, [rsp + 30h]
|
||||
movdqa xmm4, [rsp + 40h]
|
||||
movdqa xmm5, [rsp + 50h]
|
||||
|
||||
rsm
|
||||
SmmStartup ENDP
|
||||
|
||||
gcSmmInitTemplate LABEL BYTE
|
||||
|
||||
_SmmInitTemplate PROC
|
||||
DB 66h, 2eh, 8bh, 2eh ; mov ebp, cs:[@F]
|
||||
DW @L1 - _SmmInitTemplate + 8000h
|
||||
DB 66h, 81h, 0edh, 00h, 00h, 03h, 00 ; sub ebp, 30000h
|
||||
jmp bp ; jmp ebp actually
|
||||
@L1:
|
||||
DQ SmmStartup
|
||||
_SmmInitTemplate ENDP
|
||||
|
||||
gcSmmInitSize DW $ - gcSmmInitTemplate
|
||||
|
||||
SmmRelocationSemaphoreComplete PROC
|
||||
push rax
|
||||
mov rax, mRebasedFlag
|
||||
mov byte ptr [rax], 1
|
||||
pop rax
|
||||
jmp [mSmmRelocationOriginalAddress]
|
||||
SmmRelocationSemaphoreComplete ENDP
|
||||
|
||||
;
|
||||
; Semaphore code running in 32-bit mode
|
||||
;
|
||||
SmmRelocationSemaphoreComplete32 PROC
|
||||
;
|
||||
; mov byte ptr [], 1
|
||||
;
|
||||
db 0c6h, 05h
|
||||
mRebasedFlagAddr32 dd 0
|
||||
db 1
|
||||
;
|
||||
; jmp dword ptr []
|
||||
;
|
||||
db 0ffh, 25h
|
||||
mSmmRelocationOriginalAddressPtr32 dd 0
|
||||
SmmRelocationSemaphoreComplete32 ENDP
|
||||
|
||||
END
|
|
@ -0,0 +1,316 @@
|
|||
/** @file
|
||||
X64 processor specific functions to enable SMM profile.
|
||||
|
||||
Copyright (c) 2012 - 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "PiSmmCpuDxeSmm.h"
|
||||
#include "SmmProfileInternal.h"
|
||||
|
||||
//
|
||||
// Current page index.
|
||||
//
|
||||
UINTN mPFPageIndex;
|
||||
|
||||
//
|
||||
// Pool for dynamically creating page table in page fault handler.
|
||||
//
|
||||
UINT64 mPFPageBuffer;
|
||||
|
||||
//
|
||||
// Store the uplink information for each page being used.
|
||||
//
|
||||
UINT64 *mPFPageUplink[MAX_PF_PAGE_COUNT];
|
||||
|
||||
/**
|
||||
Create SMM page table for S3 path.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitSmmS3Cr3 (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS Pages;
|
||||
UINT64 *PTEntry;
|
||||
|
||||
//
|
||||
// Generate PAE page table for the first 4GB memory space
|
||||
//
|
||||
Pages = Gen4GPageTable (1, FALSE);
|
||||
|
||||
//
|
||||
// Fill Page-Table-Level4 (PML4) entry
|
||||
//
|
||||
PTEntry = (UINT64*)(UINTN)(Pages - EFI_PAGES_TO_SIZE (1));
|
||||
*PTEntry = Pages | PAGE_ATTRIBUTE_BITS;
|
||||
ZeroMem (PTEntry + 1, EFI_PAGE_SIZE - sizeof (*PTEntry));
|
||||
|
||||
//
|
||||
// Return the address of PML4 (to set CR3)
|
||||
//
|
||||
mSmmS3ResumeState->SmmS3Cr3 = (UINT32)(UINTN)PTEntry;
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
Allocate pages for creating 4KB-page based on 2MB-page when page fault happens.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitPagesForPFHandler (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
VOID *Address;
|
||||
|
||||
//
|
||||
// Pre-Allocate memory for page fault handler
|
||||
//
|
||||
Address = NULL;
|
||||
Address = AllocatePages (MAX_PF_PAGE_COUNT);
|
||||
ASSERT_EFI_ERROR (Address != NULL);
|
||||
|
||||
mPFPageBuffer = (UINT64)(UINTN) Address;
|
||||
mPFPageIndex = 0;
|
||||
ZeroMem ((VOID *) (UINTN) mPFPageBuffer, EFI_PAGE_SIZE * MAX_PF_PAGE_COUNT);
|
||||
ZeroMem (mPFPageUplink, sizeof (mPFPageUplink));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
Allocate one page for creating 4KB-page based on 2MB-page.
|
||||
|
||||
@param Uplink The address of Page-Directory entry.
|
||||
|
||||
**/
|
||||
VOID
|
||||
AcquirePage (
|
||||
UINT64 *Uplink
|
||||
)
|
||||
{
|
||||
UINT64 Address;
|
||||
|
||||
//
|
||||
// Get the buffer
|
||||
//
|
||||
Address = mPFPageBuffer + EFI_PAGES_TO_SIZE (mPFPageIndex);
|
||||
ZeroMem ((VOID *) (UINTN) Address, EFI_PAGE_SIZE);
|
||||
|
||||
//
|
||||
// Cut the previous uplink if it exists and wasn't overwritten
|
||||
//
|
||||
if ((mPFPageUplink[mPFPageIndex] != NULL) && ((*mPFPageUplink[mPFPageIndex] & PHYSICAL_ADDRESS_MASK) == Address)) {
|
||||
*mPFPageUplink[mPFPageIndex] = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Link & Record the current uplink
|
||||
//
|
||||
*Uplink = Address | PAGE_ATTRIBUTE_BITS;
|
||||
mPFPageUplink[mPFPageIndex] = Uplink;
|
||||
|
||||
mPFPageIndex = (mPFPageIndex + 1) % MAX_PF_PAGE_COUNT;
|
||||
}
|
||||
|
||||
/**
|
||||
Update page table to map the memory correctly in order to make the instruction
|
||||
which caused page fault execute successfully. And it also save the original page
|
||||
table to be restored in single-step exception.
|
||||
|
||||
@param PageTable PageTable Address.
|
||||
@param PFAddress The memory address which caused page fault exception.
|
||||
@param CpuIndex The index of the processor.
|
||||
@param ErrorCode The Error code of exception.
|
||||
@param IsValidPFAddress The flag indicates if SMM profile data need be added.
|
||||
|
||||
**/
|
||||
VOID
|
||||
RestorePageTableAbove4G (
|
||||
UINT64 *PageTable,
|
||||
UINT64 PFAddress,
|
||||
UINTN CpuIndex,
|
||||
UINTN ErrorCode,
|
||||
BOOLEAN *IsValidPFAddress
|
||||
)
|
||||
{
|
||||
UINTN PTIndex;
|
||||
UINT64 Address;
|
||||
BOOLEAN Nx;
|
||||
BOOLEAN Existed;
|
||||
UINTN Index;
|
||||
UINTN PFIndex;
|
||||
|
||||
ASSERT ((PageTable != NULL) && (IsValidPFAddress != NULL));
|
||||
|
||||
//
|
||||
// If page fault address is 4GB above.
|
||||
//
|
||||
|
||||
//
|
||||
// Check if page fault address has existed in page table.
|
||||
// If it exists in page table but page fault is generated,
|
||||
// there are 2 possible reasons: 1. present flag is set to 0; 2. instruction fetch in protected memory range.
|
||||
//
|
||||
Existed = FALSE;
|
||||
PageTable = (UINT64*)(AsmReadCr3 () & PHYSICAL_ADDRESS_MASK);
|
||||
PTIndex = BitFieldRead64 (PFAddress, 39, 47);
|
||||
if ((PageTable[PTIndex] & IA32_PG_P) != 0) {
|
||||
// PML4E
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
|
||||
PTIndex = BitFieldRead64 (PFAddress, 30, 38);
|
||||
if ((PageTable[PTIndex] & IA32_PG_P) != 0) {
|
||||
// PDPTE
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
|
||||
PTIndex = BitFieldRead64 (PFAddress, 21, 29);
|
||||
// PD
|
||||
if ((PageTable[PTIndex] & IA32_PG_PS) != 0) {
|
||||
//
|
||||
// 2MB page
|
||||
//
|
||||
Address = (UINT64)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
|
||||
if ((Address & PHYSICAL_ADDRESS_MASK & ~((1ull << 21) - 1)) == ((PFAddress & PHYSICAL_ADDRESS_MASK & ~((1ull << 21) - 1)))) {
|
||||
Existed = TRUE;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// 4KB page
|
||||
//
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
|
||||
if (PageTable != 0) {
|
||||
//
|
||||
// When there is a valid entry to map to 4KB page, need not create a new entry to map 2MB.
|
||||
//
|
||||
PTIndex = BitFieldRead64 (PFAddress, 12, 20);
|
||||
Address = (UINT64)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
|
||||
if ((Address & PHYSICAL_ADDRESS_MASK & ~((1ull << 12) - 1)) == (PFAddress & PHYSICAL_ADDRESS_MASK & ~((1ull << 12) - 1))) {
|
||||
Existed = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If page entry does not existed in page table at all, create a new entry.
|
||||
//
|
||||
if (!Existed) {
|
||||
|
||||
if (IsAddressValid (PFAddress, &Nx)) {
|
||||
//
|
||||
// If page fault address above 4GB is in protected range but it causes a page fault exception,
|
||||
// Will create a page entry for this page fault address, make page table entry as present/rw and execution-disable.
|
||||
// this access is not saved into SMM profile data.
|
||||
//
|
||||
*IsValidPFAddress = TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Create one entry in page table for page fault address.
|
||||
//
|
||||
SmiDefaultPFHandler ();
|
||||
//
|
||||
// Find the page table entry created just now.
|
||||
//
|
||||
PageTable = (UINT64*)(AsmReadCr3 () & PHYSICAL_ADDRESS_MASK);
|
||||
PFAddress = AsmReadCr2 ();
|
||||
// PML4E
|
||||
PTIndex = BitFieldRead64 (PFAddress, 39, 47);
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
|
||||
// PDPTE
|
||||
PTIndex = BitFieldRead64 (PFAddress, 30, 38);
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
|
||||
// PD
|
||||
PTIndex = BitFieldRead64 (PFAddress, 21, 29);
|
||||
Address = PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK;
|
||||
//
|
||||
// Check if 2MB-page entry need be changed to 4KB-page entry.
|
||||
//
|
||||
if (IsAddressSplit (Address)) {
|
||||
AcquirePage (&PageTable[PTIndex]);
|
||||
|
||||
// PTE
|
||||
PageTable = (UINT64*)(UINTN)(PageTable[PTIndex] & PHYSICAL_ADDRESS_MASK);
|
||||
for (Index = 0; Index < 512; Index++) {
|
||||
PageTable[Index] = Address | PAGE_ATTRIBUTE_BITS;
|
||||
if (!IsAddressValid (Address, &Nx)) {
|
||||
PageTable[Index] = PageTable[Index] & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS);
|
||||
}
|
||||
if (Nx && mXdSupported) {
|
||||
PageTable[Index] = PageTable[Index] | IA32_PG_NX;
|
||||
}
|
||||
if (Address == (PFAddress & PHYSICAL_ADDRESS_MASK & ~((1ull << 12) - 1))) {
|
||||
PTIndex = Index;
|
||||
}
|
||||
Address += SIZE_4KB;
|
||||
} // end for PT
|
||||
} else {
|
||||
//
|
||||
// Update 2MB page entry.
|
||||
//
|
||||
if (!IsAddressValid (Address, &Nx)) {
|
||||
//
|
||||
// Patch to remove present flag and rw flag.
|
||||
//
|
||||
PageTable[PTIndex] = PageTable[PTIndex] & (INTN)(INT32)(~PAGE_ATTRIBUTE_BITS);
|
||||
}
|
||||
//
|
||||
// Set XD bit to 1
|
||||
//
|
||||
if (Nx && mXdSupported) {
|
||||
PageTable[PTIndex] = PageTable[PTIndex] | IA32_PG_NX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Record old entries with non-present status
|
||||
// Old entries include the memory which instruction is at and the memory which instruction access.
|
||||
//
|
||||
//
|
||||
ASSERT (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT);
|
||||
if (mPFEntryCount[CpuIndex] < MAX_PF_ENTRY_COUNT) {
|
||||
PFIndex = mPFEntryCount[CpuIndex];
|
||||
mLastPFEntryValue[CpuIndex][PFIndex] = PageTable[PTIndex];
|
||||
mLastPFEntryPointer[CpuIndex][PFIndex] = &PageTable[PTIndex];
|
||||
mPFEntryCount[CpuIndex]++;
|
||||
}
|
||||
|
||||
//
|
||||
// Add present flag or clear XD flag to make page fault handler succeed.
|
||||
//
|
||||
PageTable[PTIndex] |= (UINT64)(PAGE_ATTRIBUTE_BITS);
|
||||
if ((ErrorCode & IA32_PF_EC_ID) != 0) {
|
||||
//
|
||||
// If page fault is caused by instruction fetch, clear XD bit in the entry.
|
||||
//
|
||||
PageTable[PTIndex] &= ~IA32_PG_NX;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
Clear TF in FLAGS.
|
||||
|
||||
@param SystemContext A pointer to the processor context when
|
||||
the interrupt occurred on the processor.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ClearTrapFlag (
|
||||
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
||||
)
|
||||
{
|
||||
SystemContext.SystemContextX64->Rflags &= (UINTN) ~BIT8;
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/** @file
|
||||
X64 processor specific header file to enable SMM profile.
|
||||
|
||||
Copyright (c) 2012 - 2015, Intel Corporation. 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 _SMM_PROFILE_ARCH_H_
|
||||
#define _SMM_PROFILE_ARCH_H_
|
||||
|
||||
#pragma pack (1)
|
||||
|
||||
typedef struct _MSR_DS_AREA_STRUCT {
|
||||
UINT64 BTSBufferBase;
|
||||
UINT64 BTSIndex;
|
||||
UINT64 BTSAbsoluteMaximum;
|
||||
UINT64 BTSInterruptThreshold;
|
||||
UINT64 PEBSBufferBase;
|
||||
UINT64 PEBSIndex;
|
||||
UINT64 PEBSAbsoluteMaximum;
|
||||
UINT64 PEBSInterruptThreshold;
|
||||
UINT64 PEBSCounterReset[2];
|
||||
UINT64 Reserved;
|
||||
} MSR_DS_AREA_STRUCT;
|
||||
|
||||
typedef struct _BRANCH_TRACE_RECORD {
|
||||
UINT64 LastBranchFrom;
|
||||
UINT64 LastBranchTo;
|
||||
UINT64 Rsvd0 : 4;
|
||||
UINT64 BranchPredicted : 1;
|
||||
UINT64 Rsvd1 : 59;
|
||||
} BRANCH_TRACE_RECORD;
|
||||
|
||||
typedef struct _PEBS_RECORD {
|
||||
UINT64 Rflags;
|
||||
UINT64 LinearIP;
|
||||
UINT64 Rax;
|
||||
UINT64 Rbx;
|
||||
UINT64 Rcx;
|
||||
UINT64 Rdx;
|
||||
UINT64 Rsi;
|
||||
UINT64 Rdi;
|
||||
UINT64 Rbp;
|
||||
UINT64 Rsp;
|
||||
UINT64 R8;
|
||||
UINT64 R9;
|
||||
UINT64 R10;
|
||||
UINT64 R11;
|
||||
UINT64 R12;
|
||||
UINT64 R13;
|
||||
UINT64 R14;
|
||||
UINT64 R15;
|
||||
} PEBS_RECORD;
|
||||
|
||||
#pragma pack ()
|
||||
|
||||
#define PHYSICAL_ADDRESS_MASK ((1ull << 52) - SIZE_4KB)
|
||||
|
||||
/**
|
||||
Update page table to map the memory correctly in order to make the instruction
|
||||
which caused page fault execute successfully. And it also save the original page
|
||||
table to be restored in single-step exception.
|
||||
|
||||
@param PageTable PageTable Address.
|
||||
@param PFAddress The memory address which caused page fault exception.
|
||||
@param CpuIndex The index of the processor.
|
||||
@param ErrorCode The Error code of exception.
|
||||
@param IsValidPFAddress The flag indicates if SMM profile data need be added.
|
||||
|
||||
**/
|
||||
VOID
|
||||
RestorePageTableAbove4G (
|
||||
UINT64 *PageTable,
|
||||
UINT64 PFAddress,
|
||||
UINTN CpuIndex,
|
||||
UINTN ErrorCode,
|
||||
BOOLEAN *IsValidPFAddress
|
||||
);
|
||||
|
||||
/**
|
||||
Create SMM page table for S3 path.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitSmmS3Cr3 (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Allocate pages for creating 4KB-page based on 2MB-page when page fault happens.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InitPagesForPFHandler (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif // _SMM_PROFILE_ARCH_H_
|
|
@ -0,0 +1,156 @@
|
|||
## @file StmCpuPkg.dec
|
||||
# This Package provides STM compatible CPU modules and libraries.
|
||||
#
|
||||
# Copyright (c) 2016, Intel Corporation. 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
DEC_SPECIFICATION = 0x00010005
|
||||
PACKAGE_NAME = StmCpuPkg
|
||||
PACKAGE_GUID = 60079593-95E6-4C01-9B39-52F575BA0F49
|
||||
PACKAGE_VERSION = 0.1
|
||||
|
||||
[Includes]
|
||||
Include
|
||||
|
||||
[LibraryClasses.IA32, LibraryClasses.X64]
|
||||
|
||||
## @libraryclass Public include file for the SMM CPU Platform Hook Library.
|
||||
##
|
||||
SmmCpuPlatformHookLib|Include/Library/SmmCpuPlatformHookLib.h
|
||||
|
||||
## @libraryclass Provides the CPU specific programming for PiSmmCpuDxeSmm module.
|
||||
##
|
||||
SmmCpuFeaturesLib|Include/Library/SmmCpuFeaturesLib.h
|
||||
|
||||
[Guids]
|
||||
gUefiCpuPkgTokenSpaceGuid = { 0xac05bf33, 0x995a, 0x4ed4, { 0xaa, 0xb8, 0xef, 0x7a, 0xe8, 0xf, 0x5c, 0xb0 }}
|
||||
|
||||
gStmCpuPkgTokenSpaceGuid = { 0x743a969b, 0x8d64, 0x44c1, { 0x99, 0x70, 0x62, 0x95, 0x13, 0xfc, 0x84, 0x49 }}
|
||||
|
||||
gMsegSmramGuid = { 0x5802bce4, 0xeeee, 0x4e33, { 0xa1, 0x30, 0xeb, 0xad, 0x27, 0xf0, 0xe4, 0x39 }}
|
||||
|
||||
[Protocols]
|
||||
## Include/Protocol/SmmCpuService.h
|
||||
gEfiSmmCpuServiceProtocolGuid = { 0x1d202cab, 0xc8ab, 0x4d5c, { 0x94, 0xf7, 0x3c, 0xfc, 0xc0, 0xd3, 0xd3, 0x35 }}
|
||||
|
||||
gEfiSmMonitorInitProtocolGuid = { 0x228f344d, 0xb3de, 0x43bb, { 0xa4, 0xd7, 0xea, 0x20, 0xb, 0x1b, 0x14, 0x82 }}
|
||||
|
||||
[PcdsFeatureFlag]
|
||||
## Indicates if SMM Profile will be enabled.
|
||||
# If enabled, instruction executions in and data accesses to memory outside of SMRAM will be logged.
|
||||
# This PCD is only for validation purpose. It should be set to false in production.<BR><BR>
|
||||
# TRUE - SMM Profile will be enabled.<BR>
|
||||
# FALSE - SMM Profile will be disabled.<BR>
|
||||
# @Prompt Enable SMM Profile.
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileEnable|FALSE|BOOLEAN|0x32132109
|
||||
|
||||
## Indicates if the SMM profile log buffer is a ring buffer.
|
||||
# If disabled, no additional log can be done when the buffer is full.<BR><BR>
|
||||
# TRUE - the SMM profile log buffer is a ring buffer.<BR>
|
||||
# FALSE - the SMM profile log buffer is a normal buffer.<BR>
|
||||
# @Prompt The SMM profile log buffer is a ring buffer.
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileRingBuffer|FALSE|BOOLEAN|0x3213210a
|
||||
|
||||
## Indicates if SMM Startup AP in a blocking fashion.
|
||||
# TRUE - SMM Startup AP in a blocking fashion.<BR>
|
||||
# FALSE - SMM Startup AP in a non-blocking fashion.<BR>
|
||||
# @Prompt SMM Startup AP in a blocking fashion.
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp|FALSE|BOOLEAN|0x32132108
|
||||
|
||||
## Indicates if SMM Stack Guard will be enabled.
|
||||
# If enabled, stack overflow in SMM can be caught which eases debugging.<BR><BR>
|
||||
# TRUE - SMM Stack Guard will be enabled.<BR>
|
||||
# FALSE - SMM Stack Guard will be disabled.<BR>
|
||||
# @Prompt Enable SMM Stack Guard.
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard|FALSE|BOOLEAN|0x1000001C
|
||||
|
||||
## Indicates if BSP election in SMM will be enabled.
|
||||
# If enabled, a BSP will be dynamically elected among all processors in each SMI.
|
||||
# Otherwise, processor 0 is always as BSP in each SMI.<BR><BR>
|
||||
# TRUE - BSP election in SMM will be enabled.<BR>
|
||||
# FALSE - BSP election in SMM will be disabled.<BR>
|
||||
# @Prompt Enable BSP election in SMM.
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection|TRUE|BOOLEAN|0x32132106
|
||||
|
||||
## Indicates if CPU SMM hot-plug will be enabled.<BR><BR>
|
||||
# TRUE - SMM CPU hot-plug will be enabled.<BR>
|
||||
# FALSE - SMM CPU hot-plug will be disabled.<BR>
|
||||
# @Prompt SMM CPU hot-plug.
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport|FALSE|BOOLEAN|0x3213210C
|
||||
|
||||
## Indicates if SMM Debug will be enabled.
|
||||
# If enabled, hardware breakpoints in SMRAM can be set outside of SMM mode and take effect in SMM.<BR><BR>
|
||||
# TRUE - SMM Debug will be enabled.<BR>
|
||||
# FALSE - SMM Debug will be disabled.<BR>
|
||||
# @Prompt Enable SMM Debug.
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug|FALSE|BOOLEAN|0x1000001B
|
||||
|
||||
## Indicates if lock SMM Feature Control MSR.<BR><BR>
|
||||
# TRUE - SMM Feature Control MSR will be locked.<BR>
|
||||
# FALSE - SMM Feature Control MSR will not be locked.<BR>
|
||||
# @Prompt Lock SMM Feature Control MSR.
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmFeatureControlMsrLock|TRUE|BOOLEAN|0x3213210B
|
||||
|
||||
## Indicates if STM is supported.<BR><BR>
|
||||
# TRUE - STM is supported.<BR>
|
||||
# FALSE - STM is unsupported.<BR>
|
||||
# @Prompt STM supported or not.
|
||||
gStmCpuPkgTokenSpaceGuid.PcdCpuStmSupport|TRUE|BOOLEAN|0x32132110
|
||||
|
||||
[PcdsFixedAtBuild, PcdsPatchableInModule]
|
||||
## Specifies buffer size in bytes for STM exception stack. The value should be a multiple of 4KB.
|
||||
# @Prompt STM exception stack size.
|
||||
gStmCpuPkgTokenSpaceGuid.PcdCpuSmmStmExceptionStackSize|0x1000|UINT32|0x32132111
|
||||
|
||||
## Specifies buffer size in bytes of MSEG. The value should be a multiple of 4KB.
|
||||
# @Prompt MSEG size.
|
||||
gStmCpuPkgTokenSpaceGuid.PcdCpuMsegSize|0x200000|UINT32|0x32132112
|
||||
|
||||
[PcdsFixedAtBuild, PcdsPatchableInModule]
|
||||
|
||||
## Specifies buffer size in bytes to save SMM profile data. The value should be a multiple of 4KB.
|
||||
# @Prompt SMM profile data buffer size.
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileSize|0x200000|UINT32|0x32132107
|
||||
|
||||
## Specifies stack size in bytes for each processor in SMM.
|
||||
# @Prompt Processor stack size in SMM.
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackSize|0x2000|UINT32|0x32132105
|
||||
|
||||
## Specifies timeout value in microseconds for the BSP in SMM to wait for all APs to come into SMM.
|
||||
# @Prompt AP synchronization timeout value in SMM.
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmApSyncTimeout|1000000|UINT64|0x32132104
|
||||
|
||||
## Indicates if SMM Code Access Check is enabled.
|
||||
# If enabled, the SMM handler cannot execute the code outside SMM regions.
|
||||
# This PCD is suggested to TRUE in production image.<BR><BR>
|
||||
# TRUE - SMM Code Access Check will be enabled.<BR>
|
||||
# FALSE - SMM Code Access Check will be disabled.<BR>
|
||||
# @Prompt SMM Code Access Check.
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmCodeAccessCheckEnable|TRUE|BOOLEAN|0x60000013
|
||||
|
||||
## Indicates the CPU synchronization method used when processing an SMI.
|
||||
# 0x00 - Traditional CPU synchronization method.<BR>
|
||||
# 0x01 - Relaxed CPU synchronization method.<BR>
|
||||
# @Prompt SMM CPU Synchronization Method.
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmSyncMode|0x00|UINT8|0x60000014
|
||||
|
||||
[PcdsDynamic, PcdsDynamicEx]
|
||||
## Contains the pointer to a CPU S3 data buffer of structure ACPI_CPU_DATA.
|
||||
# @Prompt The pointer to a CPU S3 data buffer.
|
||||
# @ValidList 0x80000001 | 0
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuS3DataAddress|0x0|UINT64|0x60000010
|
||||
|
||||
## Contains the pointer to a CPU Hot Plug Data structure if CPU hot-plug is supported.
|
||||
# @Prompt The pointer to CPU Hot Plug Data.
|
||||
# @ValidList 0x80000001 | 0
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugDataAddress|0x0|UINT64|0x60000011
|
|
@ -0,0 +1,74 @@
|
|||
## @file
|
||||
# StmCpuPkg Package
|
||||
#
|
||||
# Copyright (c) 2016, Intel Corporation. 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
PLATFORM_NAME = StmCpu
|
||||
PLATFORM_GUID = 0B2D0753-077C-4F3B-9859-55668045ECC0
|
||||
PLATFORM_VERSION = 0.1
|
||||
DSC_SPECIFICATION = 0x00010005
|
||||
OUTPUT_DIRECTORY = Build/StmCpu
|
||||
SUPPORTED_ARCHITECTURES = IA32|X64
|
||||
BUILD_TARGETS = DEBUG|RELEASE
|
||||
SKUID_IDENTIFIER = DEFAULT
|
||||
|
||||
#
|
||||
# External libraries to build package
|
||||
#
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
|
||||
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
|
||||
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
|
||||
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
|
||||
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
|
||||
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
|
||||
UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
|
||||
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
|
||||
MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
|
||||
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
|
||||
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
|
||||
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
|
||||
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
|
||||
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
|
||||
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
|
||||
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
|
||||
PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
|
||||
PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
|
||||
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
|
||||
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
|
||||
DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
|
||||
LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
|
||||
ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
|
||||
CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
|
||||
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
|
||||
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
|
||||
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
|
||||
PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
|
||||
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
|
||||
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
|
||||
|
||||
[LibraryClasses.common.DXE_SMM_DRIVER]
|
||||
SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
|
||||
MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
|
||||
SmmCpuPlatformHookLib|StmCpuPkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLibNull.inf
|
||||
SmmCpuFeaturesLib|StmCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
|
||||
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
|
||||
|
||||
[PcdsFeatureFlag]
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection|FALSE
|
||||
|
||||
[Components.IA32, Components.X64]
|
||||
StmCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/** @file
|
||||
EndOfDxe Protocol on ExitPmAuth Protocol Thunk driver.
|
||||
Some EDK platform uses ExitPmAuth and DxeSmmReadyToLock without EndOfDxe.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "EndOfDxeOnExitPmAuthThunk.h"
|
||||
|
||||
/**
|
||||
An empty dummy callback function.
|
||||
|
||||
@param[in] Event Event whose notification function is being invoked.
|
||||
@param[in] Context Pointer to the notification function's context.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
InternalEmptyCallbackFuntion (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
ExitPmAuth Protocol notification event handler.
|
||||
|
||||
@param[in] Event Event whose notification function is being invoked.
|
||||
@param[in] Context Pointer to the notification function's context.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ExitPmAuthProtocolNotification (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VOID *ExitPmAuth;
|
||||
EFI_EVENT EndOfDxeEvent;
|
||||
|
||||
//
|
||||
// Add more check to locate protocol after got event, because
|
||||
// ECP will signal this event immediately once it is register
|
||||
// just in case it is already installed.
|
||||
//
|
||||
Status = gBS->LocateProtocol (
|
||||
&gExitPmAuthProtocolGuid,
|
||||
NULL,
|
||||
&ExitPmAuth
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
// Since PI1.2.1, we need signal EndOfDxe as ExitPmAuth
|
||||
//
|
||||
Status = gBS->CreateEventEx (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK,
|
||||
InternalEmptyCallbackFuntion,
|
||||
NULL,
|
||||
&gEfiEndOfDxeEventGroupGuid,
|
||||
&EndOfDxeEvent
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
gBS->SignalEvent (EndOfDxeEvent);
|
||||
gBS->CloseEvent (EndOfDxeEvent);
|
||||
DEBUG((EFI_D_INFO,"All EndOfDxe callbacks have returned successfully\n"));
|
||||
}
|
||||
|
||||
/**
|
||||
Entry Point for DxeSmmReadyToLock Protocol on ExitPmAuth Protocol Thunk driver.
|
||||
|
||||
@param[in] ImageHandle Image handle of this driver.
|
||||
@param[in] SystemTable A Pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS The entry point is executed successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EndOfDxeMain (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
VOID *Registration;
|
||||
|
||||
//
|
||||
// Install notifications for required protocols
|
||||
//
|
||||
EfiCreateProtocolNotifyEvent (
|
||||
&gExitPmAuthProtocolGuid,
|
||||
TPL_CALLBACK,
|
||||
ExitPmAuthProtocolNotification,
|
||||
NULL,
|
||||
&Registration
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/** @file
|
||||
Include file for EndOfDxe Protocol on ExitPmAuth Protocol Thunk driver.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. 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 _END_OF_DXE_ON_EXIT_PMAUTH_THUNK_H_
|
||||
#define _END_OF_DXE_ON_EXIT_PMAUTH_THUNK_H_
|
||||
|
||||
#include <PiDxe.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Guid/EventGroup.h>
|
||||
#include <Protocol/ExitPmAuth.h>
|
||||
|
||||
#endif
|
|
@ -0,0 +1,53 @@
|
|||
## @file
|
||||
# Component description file for EndOfDxe Protocol on
|
||||
# ExitPmAuth Protocol Thunk driver.
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation. 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = EndOfDxeOnExitPmAuthThunk
|
||||
FILE_GUID = 82ECEE48-9571-4427-8485-85A5A45A0F39
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = EndOfDxeMain
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
EndOfDxeOnExitPmAuthThunk.c
|
||||
EndOfDxeOnExitPmAuthThunk.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
UefiDriverEntryPoint
|
||||
UefiBootServicesTableLib
|
||||
DebugLib
|
||||
UefiLib
|
||||
|
||||
[Guids]
|
||||
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
|
||||
|
||||
[Protocols]
|
||||
gExitPmAuthProtocolGuid ## CONSUMES
|
||||
|
||||
[Depex]
|
||||
TRUE
|
|
@ -0,0 +1,62 @@
|
|||
/** @file
|
||||
Framework SMM CPU Save State protocol on SMST2 Thunk.
|
||||
|
||||
This thunk driver produces Framework SMM CPU Save Status Protocol on SMST2.
|
||||
Some ECP platforms are still using Framework SMM CPU Save Status Protocol.
|
||||
|
||||
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials are licensed and made available under
|
||||
the terms and conditions of the BSD License that 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.
|
||||
|
||||
**/
|
||||
|
||||
#include <PiSmm.h>
|
||||
#include <Protocol/SmmCpuSaveState.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/SmmServicesTableLib.h>
|
||||
|
||||
///
|
||||
/// SMM CPU Save State Protocol instance
|
||||
///
|
||||
EFI_SMM_CPU_SAVE_STATE_PROTOCOL mSmmCpuSaveState = {
|
||||
NULL
|
||||
};
|
||||
|
||||
/**
|
||||
Entry point of PI SMM Status Code Protocol on Framework SMM Status Code Protocol thunk driver.
|
||||
|
||||
@param ImageHandle The firmware allocated handle for the EFI image.
|
||||
@param SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS The entry point is executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmCpuSaveStateProtocolOnSmst2Main (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE Handle;
|
||||
|
||||
mSmmCpuSaveState.CpuSaveState = (EFI_SMM_CPU_STATE **)gSmst->CpuSaveState;
|
||||
|
||||
Handle = NULL;
|
||||
Status = SystemTable->BootServices->InstallMultipleProtocolInterfaces(
|
||||
&Handle,
|
||||
&gEfiSmmCpuSaveStateProtocolGuid,
|
||||
&mSmmCpuSaveState,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR(Status);
|
||||
return EFI_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
## @file
|
||||
# Framework SMM CPU Save State protocol on SMST2 Thunk.
|
||||
#
|
||||
# Copyright (c) 2016, Intel Corporation. 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.
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = SmmCpuSaveStateProtocolOnSmst2
|
||||
FILE_GUID = B2E23D9B-648D-4D9F-A033-5227706C4539
|
||||
MODULE_TYPE = DXE_SMM_DRIVER
|
||||
PI_SPECIFICATION_VERSION = 0x0001000A
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = SmmCpuSaveStateProtocolOnSmst2Main
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
SmmCpuSaveStateProtocolOnSmst2.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
IntelFrameworkPkg/IntelFrameworkPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
SmmServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
DebugLib
|
||||
BaseLib
|
||||
|
||||
[Protocols]
|
||||
gEfiSmmCpuSaveStateProtocolGuid ## PRODUCES
|
||||
|
||||
[Depex]
|
||||
gEfiSmmCpuProtocolGuid
|
|
@ -0,0 +1,218 @@
|
|||
/** @file
|
||||
This is the driver that produce MsegSmram hob.
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include <PiPei.h>
|
||||
#include <Guid/SmramMemoryReserve.h>
|
||||
#include <Guid/MsegSmram.h>
|
||||
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/PeiServicesLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
|
||||
/**
|
||||
Retrieves the data structure associated witht he GUIDed HOB of type gEfiSmmPeiSmramMemoryReserveGuid
|
||||
|
||||
@retval NULL A HOB of type gEfiSmmPeiSmramMemoryReserveGuid could not be found.
|
||||
@retval !NULL A pointer to the GUID data from a HIB of type gEfiSmmPeiSmramMemoryReserveGuid
|
||||
|
||||
**/
|
||||
EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *
|
||||
GetSrmamHobData (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
VOID *GuidHob;
|
||||
|
||||
//
|
||||
// Search SmramMemoryReserve HOB that describes SMRAM region
|
||||
//
|
||||
GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);
|
||||
if (GuidHob == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
return (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)GET_GUID_HOB_DATA (GuidHob);
|
||||
}
|
||||
|
||||
/**
|
||||
This routine will split SmramReserve hob to reserve Mseg page for SMRAM content.
|
||||
|
||||
@retval EFI_SUCCESS The gEfiSmmPeiSmramMemoryReserveGuid is splited successfully.
|
||||
@retval EFI_NOT_FOUND The gEfiSmmPeiSmramMemoryReserveGuid is not found.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SplitSmramReserveHob (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_HOB_GUID_TYPE *GuidHob;
|
||||
EFI_PEI_HOB_POINTERS Hob;
|
||||
EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;
|
||||
EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *NewDescriptorBlock;
|
||||
UINTN BufferSize;
|
||||
UINTN SmramRanges;
|
||||
UINT32 MsegSize;
|
||||
UINT32 MsegBase;
|
||||
|
||||
MsegSize = PcdGet32 (PcdCpuMsegSize);
|
||||
|
||||
//
|
||||
// Retrieve the GUID HOB data that contains the set of SMRAM descriptyors
|
||||
//
|
||||
GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);
|
||||
if (GuidHob == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
DescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)GET_GUID_HOB_DATA (GuidHob);
|
||||
|
||||
//
|
||||
// Allocate one extra EFI_SMRAM_DESCRIPTOR to describe a page of SMRAM memory that contains a pointer
|
||||
// to the SMM Services Table that is required on the S3 resume path
|
||||
//
|
||||
SmramRanges = DescriptorBlock->NumberOfSmmReservedRegions;
|
||||
BufferSize = sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK) + (SmramRanges * sizeof (EFI_SMRAM_DESCRIPTOR));
|
||||
|
||||
Hob.Raw = BuildGuidHob (
|
||||
&gEfiSmmPeiSmramMemoryReserveGuid,
|
||||
BufferSize
|
||||
);
|
||||
ASSERT (Hob.Raw);
|
||||
NewDescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)Hob.Raw;
|
||||
|
||||
//
|
||||
// Copy old EFI_SMRAM_HOB_DESCRIPTOR_BLOCK to new allocated region
|
||||
//
|
||||
CopyMem ((VOID *)Hob.Raw, DescriptorBlock, BufferSize - sizeof(EFI_SMRAM_DESCRIPTOR));
|
||||
|
||||
//
|
||||
// Increase the number of SMRAM descriptors by 1 to make room for the ALLOCATED descriptor of size EFI_PAGE_SIZE
|
||||
//
|
||||
NewDescriptorBlock->NumberOfSmmReservedRegions = (UINT32)(SmramRanges + 1);
|
||||
|
||||
ASSERT (SmramRanges >= 1);
|
||||
//
|
||||
// Copy last entry to the end - we assume TSEG is last entry, which is same assumption as R8 CPU/SMM driver
|
||||
//
|
||||
CopyMem (&NewDescriptorBlock->Descriptor[SmramRanges], &NewDescriptorBlock->Descriptor[SmramRanges - 1], sizeof(EFI_SMRAM_DESCRIPTOR));
|
||||
|
||||
//
|
||||
// Reduce the size of the last entry with MsegSize.
|
||||
//
|
||||
ASSERT (NewDescriptorBlock->Descriptor[SmramRanges].PhysicalSize > MsegSize);
|
||||
NewDescriptorBlock->Descriptor[SmramRanges].PhysicalSize -= MsegSize;
|
||||
|
||||
//
|
||||
// Add the last but 1 entry with size of MsegSize and put into the ALLOCATED state
|
||||
//
|
||||
MsegBase = (UINT32)(NewDescriptorBlock->Descriptor[SmramRanges].CpuStart + NewDescriptorBlock->Descriptor[SmramRanges].PhysicalSize);
|
||||
NewDescriptorBlock->Descriptor[SmramRanges - 1].PhysicalStart = MsegBase;
|
||||
NewDescriptorBlock->Descriptor[SmramRanges - 1].CpuStart = MsegBase;
|
||||
NewDescriptorBlock->Descriptor[SmramRanges - 1].PhysicalSize = MsegSize;
|
||||
NewDescriptorBlock->Descriptor[SmramRanges - 1].RegionState |= EFI_ALLOCATED;
|
||||
|
||||
//
|
||||
// Last step, we can scrub old one
|
||||
//
|
||||
ZeroMem (&GuidHob->Name, sizeof(GuidHob->Name));
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This routine will create MsegSmram hob to hold MsegSmramInfo.
|
||||
|
||||
@retval EFI_SUCCESS The MsegSmramHob is created successfully.
|
||||
@retval EFI_NOT_FOUND The gEfiSmmPeiSmramMemoryReserveGuid is not found.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CreateMsegSmramHob (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_PEI_HOB_POINTERS Hob;
|
||||
EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;
|
||||
UINTN SmramRanges;
|
||||
|
||||
//
|
||||
// Retrieve the GUID HOB data that contains the set of SMRAM descriptyors
|
||||
//
|
||||
DescriptorBlock = GetSrmamHobData ();
|
||||
if (DescriptorBlock == NULL) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
Hob.Raw = BuildGuidHob (
|
||||
&gMsegSmramGuid,
|
||||
sizeof (EFI_SMRAM_DESCRIPTOR)
|
||||
);
|
||||
ASSERT (Hob.Raw);
|
||||
|
||||
//
|
||||
// It should be already patch, so just copy last but 1 region directly.
|
||||
//
|
||||
SmramRanges = DescriptorBlock->NumberOfSmmReservedRegions;
|
||||
ASSERT (SmramRanges >= 2);
|
||||
if (SmramRanges >= 2) {
|
||||
CopyMem ((VOID *)Hob.Raw, &DescriptorBlock->Descriptor[SmramRanges - 2], sizeof (EFI_SMRAM_DESCRIPTOR));
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Driver Entry for MsegSmram PEIM
|
||||
|
||||
@param FileHandle Handle of the file being invoked.
|
||||
@param PeiServices Describes the list of possible PEI Services.
|
||||
|
||||
@retval EFI_SUCCESS Success create gMsegSmramGuid and
|
||||
split gEfiSmmPeiSmramMemoryReserveGuid.
|
||||
@retval EFI_NOT_FOUND Can not get gEfiSmmPeiSmramMemoryReserveGuid hob
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
MsegSmramHobEntry (
|
||||
IN EFI_PEI_FILE_HANDLE FileHandle,
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (PcdGet32 (PcdCpuMsegSize) == 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Split SmramReserve hob.
|
||||
//
|
||||
Status = SplitSmramReserveHob ();
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Create MsegSmram hob.
|
||||
//
|
||||
Status = CreateMsegSmramHob ();
|
||||
|
||||
return Status;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
## @file
|
||||
# Component description file for MsegSmramPeim.
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation. 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = MsegSmramPeim
|
||||
FILE_GUID = D2ABC888-AE13-4e3b-BCEE-5DE368FA4E72
|
||||
MODULE_TYPE = PEIM
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = MsegSmramHobEntry
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
MsegSmramPei.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
IntelFrameworkPkg/IntelFrameworkPkg.dec
|
||||
StmCpuPkg/StmCpuPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
PeimEntryPoint
|
||||
MemoryAllocationLib
|
||||
DebugLib
|
||||
HobLib
|
||||
PeiServicesLib
|
||||
BaseMemoryLib
|
||||
|
||||
[Pcd]
|
||||
gStmCpuPkgTokenSpaceGuid.PcdCpuMsegSize ## CONSUMES
|
||||
|
||||
[Guids]
|
||||
gEfiSmmPeiSmramMemoryReserveGuid ## CONSUMES ## HOB
|
||||
gMsegSmramGuid ## PRODUCES ## HOB
|
||||
|
||||
[Depex]
|
||||
gEfiPeiMemoryDiscoveredPpiGuid
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,39 @@
|
|||
## @file StmPlatformSamplePkg.Sample.fdf
|
||||
#
|
||||
# Copyright (c) 2015 - 2016, Intel Corporation. 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.
|
||||
#
|
||||
##
|
||||
|
||||
[FV.FVRECOVERY]
|
||||
|
||||
!if $(STM_ENABLE) == TRUE
|
||||
INF StmPlatformSamplePkg/MsegSmramPei/MsegSmramPei.inf
|
||||
!endif
|
||||
|
||||
[FV.FVMAIN]
|
||||
|
||||
!if $(STM_ENABLE) == TRUE
|
||||
INF StmCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
|
||||
!else
|
||||
# original PiSmmCpuDxeSmm.inf
|
||||
!endif
|
||||
|
||||
!if $(STM_ENABLE) == TRUE
|
||||
INF StmPlatformSamplePkg/StmPlatformSmm/StmPlatformSmm.inf
|
||||
INF StmPlatformSamplePkg/Compatibility/EndOfDxeOnExitPmAuthThunk/EndOfDxeOnExitPmAuthThunk.inf
|
||||
INF StmPlatformSamplePkg/Compatibility/SmmCpuSaveStateProtocolOnSmst2/SmmCpuSaveStateProtocolOnSmst2.inf
|
||||
|
||||
FILE FREEFORM = PCD(gStmPlatformTokenSpaceGuid.PcdStmBinFile) {
|
||||
SECTION RAW = StmPlatformSamplePkg/StmBin/X64$(TARGET)/Stm.bin
|
||||
}
|
||||
INF USE=X64 StmPlatformSamplePkg/TestBin/X64$(TARGET)/Frm.inf
|
||||
INF USE=X64 StmPlatformSamplePkg/TestBin/X64$(TARGET)/StmService.inf
|
||||
INF USE=X64 StmPlatformSamplePkg/TestBin/X64$(TARGET)/FrmLoader.inf
|
||||
!endif
|
|
@ -0,0 +1,26 @@
|
|||
## @file StmPlatformSamplePkg.dec
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation. 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
DEC_SPECIFICATION = 0x00010005
|
||||
PACKAGE_NAME = StmPlatformSamplePkg
|
||||
PACKAGE_GUID = C6EEF1B6-499F-4eea-BAF0-4E7C211389DF
|
||||
PACKAGE_VERSION = 0.1
|
||||
|
||||
[Includes.common]
|
||||
|
||||
[Guids]
|
||||
gStmPlatformTokenSpaceGuid = { 0x49a5d4e2, 0x5279, 0x402e, { 0x9a, 0xb1, 0x8d, 0x80, 0xb7, 0xe8, 0x8c, 0xf7 }}
|
||||
|
||||
[PcdsFixedAtBuild]
|
||||
gStmPlatformTokenSpaceGuid.PcdStmBinFile|{ 0x06, 0x3E, 0xCA, 0xAC, 0x64, 0x3C, 0x09, 0x45, 0xA6, 0x87, 0xDD, 0xC7, 0x6F, 0x71, 0xB5, 0x61 }|VOID*|0x20000001
|
|
@ -0,0 +1,73 @@
|
|||
## @file StmPlatformSamplePkg.dsc
|
||||
#
|
||||
# Copyright (c) 2015 - 2016, Intel Corporation. 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
PLATFORM_NAME = StmPlatformSamplePkg
|
||||
PLATFORM_GUID = 6F86CFEE-D1B0-4226-BE07-91C7D3B892CC
|
||||
PLATFORM_VERSION = 0.1
|
||||
DSC_SPECIFICATION = 0x00010005
|
||||
OUTPUT_DIRECTORY = Build/StmPlatformSamplePkg
|
||||
SUPPORTED_ARCHITECTURES = IA32|X64
|
||||
BUILD_TARGETS = DEBUG|RELEASE
|
||||
SKUID_IDENTIFIER = DEFAULT
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
|
||||
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
|
||||
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
|
||||
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
|
||||
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
|
||||
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
|
||||
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
|
||||
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
|
||||
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
|
||||
PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
|
||||
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
|
||||
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
|
||||
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
|
||||
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
|
||||
PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
|
||||
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
|
||||
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
|
||||
UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
|
||||
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
|
||||
DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
|
||||
SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf
|
||||
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
|
||||
|
||||
[LibraryClasses.common.PEIM]
|
||||
PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
|
||||
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
|
||||
HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
|
||||
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
|
||||
PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
|
||||
PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
|
||||
|
||||
[LibraryClasses.common.DXE_DRIVER]
|
||||
|
||||
[LibraryClasses.common.DXE_SMM_DRIVER]
|
||||
SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
|
||||
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
|
||||
IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
|
||||
|
||||
[Components]
|
||||
StmPlatformSamplePkg/MsegSmramPei/MsegSmramPei.inf
|
||||
StmPlatformSamplePkg/StmPlatformSmm/StmPlatformSmm.inf
|
||||
StmPlatformSamplePkg/Compatibility/EndOfDxeOnExitPmAuthThunk/EndOfDxeOnExitPmAuthThunk.inf
|
||||
StmPlatformSamplePkg/Compatibility/SmmCpuSaveStateProtocolOnSmst2/SmmCpuSaveStateProtocolOnSmst2.inf
|
||||
|
||||
[PcdsFixedAtBuild]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x0f
|
||||
gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80000000
|
||||
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x06
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
/** @file
|
||||
STM platform SMM resource
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "StmPlatformSmm.h"
|
||||
|
||||
#define RDWR_ACCS 3
|
||||
#define FULL_ACCS 7
|
||||
|
||||
UINT32 mMaxBus;
|
||||
UINT32 mTsegBase;
|
||||
UINT32 mTsegSize;
|
||||
UINT16 mPmBase;
|
||||
|
||||
//
|
||||
// Fixed memory ranges
|
||||
//
|
||||
|
||||
//
|
||||
// TSEG memory!
|
||||
//
|
||||
STM_RSC_MEM_DESC RscTsegMemory = {
|
||||
{MEM_RANGE, sizeof (STM_RSC_MEM_DESC)},
|
||||
0,
|
||||
0,
|
||||
FULL_ACCS
|
||||
};
|
||||
//
|
||||
// Flash part
|
||||
//
|
||||
STM_RSC_MEM_DESC RscSpiMemory = {
|
||||
{MEM_RANGE, sizeof (STM_RSC_MEM_DESC)},
|
||||
0xFE000000,
|
||||
0x01000000,
|
||||
FULL_ACCS
|
||||
};
|
||||
//
|
||||
// ACPI
|
||||
//
|
||||
STM_RSC_IO_DESC RscPmIo = {
|
||||
{IO_RANGE, sizeof (STM_RSC_IO_DESC)},
|
||||
0,
|
||||
128
|
||||
};
|
||||
|
||||
//
|
||||
// PCIE MMIO
|
||||
//
|
||||
STM_RSC_MMIO_DESC RscPcieMmio = {
|
||||
{MMIO_RANGE, sizeof (STM_RSC_MMIO_DESC)},
|
||||
0,
|
||||
0, // Length
|
||||
RDWR_ACCS
|
||||
};
|
||||
//
|
||||
// Local APIC
|
||||
//
|
||||
STM_RSC_MMIO_DESC RscApicMmio = {
|
||||
{MMIO_RANGE, sizeof (STM_RSC_MMIO_DESC)},
|
||||
0,
|
||||
0x400,
|
||||
RDWR_ACCS
|
||||
};
|
||||
//
|
||||
// Software SMI
|
||||
//
|
||||
STM_RSC_TRAPPED_IO_DESC RscSwSmiTrapIo = {
|
||||
{TRAPPED_IO_RANGE, sizeof (STM_RSC_TRAPPED_IO_DESC)},
|
||||
0xB2,
|
||||
2
|
||||
};
|
||||
//
|
||||
// End of list
|
||||
//
|
||||
STM_RSC_END RscListEnd = {
|
||||
{END_OF_RESOURCES, sizeof (STM_RSC_END)},
|
||||
0
|
||||
};
|
||||
|
||||
//
|
||||
// Common PCI devices
|
||||
//
|
||||
//
|
||||
// LPC bridge
|
||||
//
|
||||
STM_RSC_PCI_CFG_DESC RscLpcBridgePci = {
|
||||
{PCI_CFG_RANGE, sizeof (STM_RSC_PCI_CFG_DESC)},
|
||||
RDWR_ACCS, 0,
|
||||
0,
|
||||
0x1000,
|
||||
0,
|
||||
0,
|
||||
{
|
||||
{1, 1, sizeof(STM_PCI_DEVICE_PATH_NODE), LPC_FUNCTION, LPC_DEVICE},
|
||||
},
|
||||
};
|
||||
|
||||
//
|
||||
// Template for MSR resources.
|
||||
//
|
||||
STM_RSC_MSR_DESC RscMsrTpl = {
|
||||
{MACHINE_SPECIFIC_REG, sizeof (STM_RSC_MSR_DESC)},
|
||||
};
|
||||
|
||||
//
|
||||
// MSR indices to register
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 MsrIndex;
|
||||
UINT64 ReadMask;
|
||||
UINT64 WriteMask;
|
||||
} MSR_TABLE_ENTRY;
|
||||
|
||||
MSR_TABLE_ENTRY MsrTable[] = {
|
||||
// Index Read Write // MASK64 means need access, MASK0 means no need access.
|
||||
{SMRR_PHYSBASE_MSR, MASK64, MASK0},
|
||||
{SMRR_PHYSMASK_MSR, MASK64, MASK0},
|
||||
};
|
||||
|
||||
/**
|
||||
Reads a 64-bit PCI configuration register.
|
||||
|
||||
@param Address Address that encodes the PCI Bus, Device, Function and
|
||||
Register.
|
||||
|
||||
@return The read value from the PCI configuration register.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
PciRead64 (
|
||||
IN UINTN Address
|
||||
)
|
||||
{
|
||||
UINT64 RegLow;
|
||||
UINT64 RegHigh;
|
||||
|
||||
RegLow = (UINT64) PciRead32(Address);
|
||||
RegHigh = (UINT64) PciRead32(Address + 4);
|
||||
|
||||
return (LShiftU64 (RegHigh, 32) + RegLow);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
BIOS resources initialization.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ResourceInit (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
mMaxBus = 255;
|
||||
|
||||
mPmBase = (UINT16) PciRead16 (
|
||||
PCI_LIB_ADDRESS (
|
||||
LPC_BUS,
|
||||
LPC_DEVICE,
|
||||
LPC_FUNCTION,
|
||||
R_ACPI_PM_BASE)
|
||||
) & ACPI_PM_BASE_MASK;
|
||||
|
||||
mTsegBase = (UINT32)AsmReadMsr64 (SMRR_PHYSBASE_MSR) & 0xFFFFF000;
|
||||
mTsegSize = (UINT32)(~((UINT32)AsmReadMsr64 (SMRR_PHYSMASK_MSR) & 0xFFFFF000) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Fix up PCIE resource.
|
||||
|
||||
**/
|
||||
VOID
|
||||
FixupPciexResource (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// Find max bus number and PCIEX length
|
||||
//
|
||||
RscPcieMmio.Length = 0x10000000; // 256 MB
|
||||
RscPcieMmio.Base = PcdGet64 (PcdPciExpressBaseAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Add basic resources to BIOS resource database.
|
||||
|
||||
**/
|
||||
VOID
|
||||
AddSimpleResources (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Fix-up values
|
||||
//
|
||||
RscTsegMemory.Base = mTsegBase;
|
||||
RscTsegMemory.Length = mTsegSize;
|
||||
|
||||
RscPmIo.Base = (UINT16) mPmBase;
|
||||
|
||||
//
|
||||
// Local APIC. We assume that all thteads are programmed identically
|
||||
// despite that it is possible to have individual APIC address for
|
||||
// each of the threads. If this is the case this programming should
|
||||
// be corrected.
|
||||
//
|
||||
RscApicMmio.Base = AsmReadMsr64 (IA32_APIC_BASE_MSR_INDEX) & 0xFFFFFF000ull;
|
||||
|
||||
//
|
||||
// PCIEX BAR
|
||||
//
|
||||
FixupPciexResource ();
|
||||
|
||||
Status = mSmMonitorInitProtocol->AddPiResource((VOID *) &RscTsegMemory, 0);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
Status = mSmMonitorInitProtocol->AddPiResource((VOID *) &RscLpcBridgePci, 1);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Add MSR resources to BIOS resource database.
|
||||
|
||||
**/
|
||||
VOID
|
||||
AddMsrResources (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Index;
|
||||
|
||||
for (Index = 0; Index < sizeof(MsrTable)/sizeof(MsrTable[0]); Index ++) {
|
||||
|
||||
RscMsrTpl.MsrIndex = (UINT32) MsrTable[Index].MsrIndex;
|
||||
RscMsrTpl.ReadMask = (UINT64) MsrTable[Index].ReadMask;
|
||||
RscMsrTpl.WriteMask = (UINT64) MsrTable[Index].WriteMask;
|
||||
|
||||
Status = mSmMonitorInitProtocol->AddPiResource ((VOID *) &RscMsrTpl, 1);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Add resources to BIOS resource database.
|
||||
|
||||
**/
|
||||
VOID
|
||||
AddResourcesCmd (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ResourceInit ();
|
||||
|
||||
AddSimpleResources();
|
||||
|
||||
AddMsrResources ();
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/** @file
|
||||
STM platform SMM resource
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. 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 _STM_PLATFORM_RESOURCE_H_
|
||||
#define _STM_PLATFORM_RESOURCE_H_
|
||||
|
||||
#define MASK0 0
|
||||
#define MASK64 0xFFFFFFFFFFFFFFFFull
|
||||
|
||||
//
|
||||
// LPC
|
||||
//
|
||||
#define LPC_BUS 0
|
||||
#define LPC_DEVICE 31
|
||||
#define LPC_FUNCTION 0
|
||||
#define R_ACPI_PM_BASE 0x40
|
||||
#define ACPI_PM_BASE_MASK 0xFFF8
|
||||
|
||||
//
|
||||
// MSRs
|
||||
//
|
||||
#define IA32_APIC_BASE_MSR_INDEX 0x1B
|
||||
#define SMRR_PHYSBASE_MSR 0x1F2
|
||||
#define SMRR_PHYSMASK_MSR 0x1F3
|
||||
|
||||
/**
|
||||
|
||||
Add resources to BIOS resource database.
|
||||
|
||||
**/
|
||||
VOID
|
||||
AddResourcesCmd (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,128 @@
|
|||
/** @file
|
||||
STM platform SMM API
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "StmPlatformSmm.h"
|
||||
|
||||
EFI_SM_MONITOR_INIT_PROTOCOL *mSmMonitorInitProtocol;
|
||||
|
||||
/**
|
||||
SMM End Of Dxe event notification handler.
|
||||
|
||||
Add system resource for STM.
|
||||
|
||||
@param[in] Protocol Points to the protocol's unique identifier.
|
||||
@param[in] Interface Points to the interface instance.
|
||||
@param[in] Handle The handle on which the interface was installed.
|
||||
|
||||
@retval EFI_SUCCESS Notification handler runs successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmEndOfDxeEventNotify (
|
||||
IN CONST EFI_GUID *Protocol,
|
||||
IN VOID *Interface,
|
||||
IN EFI_HANDLE Handle
|
||||
)
|
||||
{
|
||||
AddResourcesCmd ();
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Load STM image.
|
||||
|
||||
@retval EFI_SUCCESS STM is loaded to MSEG
|
||||
@retval EFI_BUFFER_TOO_SMALL MSEG is too small
|
||||
@retval EFI_UNSUPPORTED MSEG is not enabled
|
||||
**/
|
||||
EFI_STATUS
|
||||
LoadStmImage (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VOID *StmImageBuffer;
|
||||
UINTN StmImageSize;
|
||||
|
||||
//
|
||||
// Extract STM image from FV
|
||||
//
|
||||
StmImageBuffer = NULL;
|
||||
StmImageSize = 0;
|
||||
|
||||
Status = GetSectionFromAnyFv (
|
||||
PcdGetPtr(PcdStmBinFile),
|
||||
EFI_SECTION_RAW,
|
||||
0,
|
||||
&StmImageBuffer,
|
||||
&StmImageSize
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
Status = mSmMonitorInitProtocol->LoadMonitor ((EFI_PHYSICAL_ADDRESS)(UINTN)StmImageBuffer, StmImageSize);
|
||||
DEBUG ((EFI_D_ERROR, "mSmMonitorInitProtocol->LoadMonitor - %r\n", Status));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
gBS->FreePool ((VOID *)((UINTN)StmImageBuffer));
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
STM platform SMM driver entry point function.
|
||||
|
||||
@param ImageHandle image handle for this driver image
|
||||
@param SystemTable pointer to the EFI System Table
|
||||
|
||||
@retval EFI_SUCCESS
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InstallStmPlatformSmm (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VOID *Registration;
|
||||
|
||||
Status = gSmst->SmmLocateProtocol (
|
||||
&gEfiSmMonitorInitProtocolGuid,
|
||||
NULL,
|
||||
(VOID **)&mSmMonitorInitProtocol
|
||||
);
|
||||
if (EFI_ERROR(Status) || (mSmMonitorInitProtocol == NULL)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Status = LoadStmImage ();
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// We have to add resource here because it depends on PCI bus enumeration.
|
||||
// So we use EndOfDxe event.
|
||||
//
|
||||
Status = gSmst->SmmRegisterProtocolNotify (
|
||||
&gEfiSmmEndOfDxeProtocolGuid,
|
||||
SmmEndOfDxeEventNotify,
|
||||
&Registration
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/** @file
|
||||
STM platform SMM API
|
||||
|
||||
Copyright (c) 2015, Intel Corporation. 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 _STM_PLATFORM_SMM_H_
|
||||
#define _STM_PLATFORM_SMM_H_
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/DxeServicesLib.h>
|
||||
#include <Library/SmmServicesTableLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PciLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
|
||||
#include <Protocol/SmmReadyToLock.h>
|
||||
#include <Protocol/SmmEndOfDxe.h>
|
||||
#include <Protocol/SmmCpu.h>
|
||||
|
||||
#include <IndustryStandard/Pci30.h>
|
||||
|
||||
#include <Protocol/SmMonitorInit.h>
|
||||
|
||||
#include <Library/PcdLib.h>
|
||||
|
||||
#include "StmPlatformResource.h"
|
||||
|
||||
extern EFI_SM_MONITOR_INIT_PROTOCOL *mSmMonitorInitProtocol;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,62 @@
|
|||
## @file
|
||||
# Component description file for StmPlatformSmm module.
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation. 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = StmPlatformSmm
|
||||
FILE_GUID = BC0E8BB2-B69D-41cf-BF57-BB908AB0C5AA
|
||||
MODULE_TYPE = DXE_SMM_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
PI_SPECIFICATION_VERSION = 0x0001000A
|
||||
ENTRY_POINT = InstallStmPlatformSmm
|
||||
|
||||
[Sources]
|
||||
StmPlatformSmm.c
|
||||
StmPlatformSmm.h
|
||||
StmPlatformResource.c
|
||||
StmPlatformResource.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
IntelFrameworkPkg/IntelFrameworkPkg.dec
|
||||
StmCpuPkg/StmCpuPkg.dec
|
||||
StmPlatformSamplePkg/StmPlatformSamplePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
UefiDriverEntryPoint
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
DxeServicesLib
|
||||
UefiBootServicesTableLib
|
||||
SmmServicesTableLib
|
||||
IoLib
|
||||
PciLib
|
||||
IntrinsicLib
|
||||
|
||||
[Pcd]
|
||||
gStmPlatformTokenSpaceGuid.PcdStmBinFile ## CONSUMES
|
||||
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES
|
||||
|
||||
[Protocols]
|
||||
gEfiSmmCpuProtocolGuid ## CONSUMES
|
||||
gEfiSmmEndOfDxeProtocolGuid ## CONSUMES
|
||||
gEfiSmMonitorInitProtocolGuid ## PRODUCES
|
||||
|
||||
[Depex]
|
||||
gEfiSmmCpuProtocolGuid AND
|
||||
gEfiSmmSwDispatch2ProtocolGuid
|
||||
|
||||
[BuildOptions]
|
||||
MSFT:*_*_*_CC_FLAGS = /Od /GL-
|
|
@ -0,0 +1 @@
|
|||
|
Binary file not shown.
|
@ -0,0 +1,29 @@
|
|||
## @file
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation. 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.
|
||||
#
|
||||
#
|
||||
##
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010006
|
||||
BASE_NAME = Frm
|
||||
FILE_GUID = 0F50B4B1-C62F-4902-B3AF-E79DBED20109
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
[Binaries.X64]
|
||||
PE32|Frm.efi|*
|
||||
DXE_DEPEX|Frm.depex|*
|
||||
|
||||
[Depex]
|
||||
FALSE
|
||||
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,34 @@
|
|||
## @file
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation. 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.
|
||||
#
|
||||
#
|
||||
##
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010006
|
||||
BASE_NAME = FrmLoader
|
||||
FILE_GUID = BBA4C424-A903-4c2d-BF4A-C54F4A814CB3
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
[Binaries.X64]
|
||||
PE32|FrmLoader.efi|*
|
||||
# DXE_DEPEX|FrmLoader.depex|*
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
IntelFrameworkPkg/IntelFrameworkPkg.dec
|
||||
|
||||
#[Depex]
|
||||
# gEfiCpuArchProtocolGuid AND
|
||||
# gEfiMpServiceProtocolGuid
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
|
Binary file not shown.
|
@ -0,0 +1,33 @@
|
|||
## @file
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation. 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.
|
||||
#
|
||||
#
|
||||
##
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010006
|
||||
BASE_NAME = StmService
|
||||
FILE_GUID = 04E95A7C-07ED-48A7-9462-0E5B1C3B049F
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
[Binaries.X64]
|
||||
PE32|StmService.efi|*
|
||||
DXE_DEPEX|StmService.depex|*
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
IntelFrameworkPkg/IntelFrameworkPkg.dec
|
||||
|
||||
[Depex]
|
||||
TRUE
|
|
@ -0,0 +1 @@
|
|||
|
Binary file not shown.
|
@ -0,0 +1,29 @@
|
|||
## @file
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation. 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.
|
||||
#
|
||||
#
|
||||
##
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010006
|
||||
BASE_NAME = Frm
|
||||
FILE_GUID = 0F50B4B1-C62F-4902-B3AF-E79DBED20109
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
[Binaries.X64]
|
||||
PE32|Frm.efi|*
|
||||
DXE_DEPEX|Frm.depex|*
|
||||
|
||||
[Depex]
|
||||
FALSE
|
||||
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,34 @@
|
|||
## @file
|
||||
#
|
||||
# Copyright (c) 2015, Intel Corporation. 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.
|
||||
#
|
||||
#
|
||||
##
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010006
|
||||
BASE_NAME = FrmLoader
|
||||
FILE_GUID = BBA4C424-A903-4c2d-BF4A-C54F4A814CB3
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
[Binaries.X64]
|
||||
PE32|FrmLoader.efi|*
|
||||
# DXE_DEPEX|FrmLoader.depex|*
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
IntelFrameworkPkg/IntelFrameworkPkg.dec
|
||||
|
||||
#[Depex]
|
||||
# gEfiCpuArchProtocolGuid AND
|
||||
# gEfiMpServiceProtocolGuid
|
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue