From b7c51c9cf4864df6aabb99a1ae843becd577237c Mon Sep 17 00:00:00 2001 From: raywu Date: Fri, 15 Jun 2018 00:00:50 +0800 Subject: init. 1AQQW051 --- Core/EM/SMM/SmmPiSmst.c | 1827 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1827 insertions(+) create mode 100644 Core/EM/SMM/SmmPiSmst.c (limited to 'Core/EM/SMM/SmmPiSmst.c') diff --git a/Core/EM/SMM/SmmPiSmst.c b/Core/EM/SMM/SmmPiSmst.c new file mode 100644 index 0000000..f6a676b --- /dev/null +++ b/Core/EM/SMM/SmmPiSmst.c @@ -0,0 +1,1827 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +/** SmmPiSmst.c - Protocol functions are modified verision from Intel's SMM source. + + Copyright (c) 2009, Intel Corporation + All rights reserved. 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. + +**/ + +//********************************************************************** +// $Header: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmPiSmst.c 6 3/31/11 6:52p Markw $ +// +// $Revision: 6 $ +// +// $Date: 3/31/11 6:52p $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/SOURCE/Modules/SMM/SMMDispatcher/SmmPiSmst.c $ +// +// 6 3/31/11 6:52p Markw +// Add back revisions 2 to 4. +// +// 5 3/31/11 6:45p Markw +// [TAG] EIP57440 +// [Category] New Feature +// [Description] Add PI 1.1 SMM support for reading/writing floating +// point/smm save state. +// +// [Files] CpuCspLib.h, CpuCspLib.c, SmmPiSmst.c +// +// 4 3/15/11 2:35p Markw +// Copyright header update. +// +// 3 3/14/11 3:19p Markw +// Update for EIP 53481. +// Rename gSmmFirmwareVender to gSmmFirmwareVendor. +// For gSmmFirmwareVendor use CONVERT_TO_WSTRING(CORE_VENDOR); instead of +// AMI. +// +// 2 3/08/11 2:00p Markw +// Update headers and spacing. +// +// 1 2/07/11 3:28p Markw +// [TAG] EIP53481 +// [Category] New Feature +// [Description] Add PIWG 1.1 SMM support +// [Files] Smm.sdl, SmmPrivateShared.h, SmmDispatcher.mak, +// SmmDispatcher.h, SmmDispatcher.c, +// Smst.c, SmmPiSmst.c, SmmInit.c, SmmBase.c, SmmBase2.c, +// SmmDriverDispatcher.c, Smm Framewwork Protocol files, SmmPi.h, +// Smm Pi Protocol files, SmmPciRbio files +// +//********************************************************************** + +// +//--------------------------------------------------------------------------- +// +// Name: SmmPiSmst.c +// +// Description: PI Smst functions. +// +//--------------------------------------------------------------------------- +// + +//This include should come first. +//#include "SmmPi.h" +#include "SmmPrivateShared.h" +#include +#include +#if SMM_USE_PI +#include "SmmDispatcher.h" +#include +#include +#endif + +CHAR16 gSmmFirmwareVendor[] = CONVERT_TO_WSTRING(CORE_VENDOR); + +extern UINT8 **gSmmBase; + +//TODOx64: move it to a library header +VOID CPULib_Pause(); + +VOID *Allocate(VOID *Base, UINTN Size,UINTN Alignment); + +EFI_STATUS AllocateABSegPages( + IN EFI_ALLOCATE_TYPE Type, + IN UINTN NumberOfPages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory +); +EFI_STATUS FreeABSegPages( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages +); + +BOOLEAN Free(VOID *Buffer); +BOOLEAN Free4kPages(VOID *StartAddress,UINTN Pages); + +EFI_STATUS InterruptManage( + IN CONST EFI_GUID *HandlerType, + IN CONST VOID *Context OPTIONAL, + IN OUT VOID *CommBuffer OPTIONAL, + IN OUT UINTN *CommBufferSize OPTIONAL +); + +VOID UpdateFrameworkSmmConfigTable(IN EFI_CONFIGURATION_TABLE *SmmConfigurationTable, IN UINTN NumberOfTableEntries); + +UINT8* Align2n(UINT8 *Value,UINTN Alignment); + +#if SMM_USE_FRAMEWORK +extern EFI_SMM_SYSTEM_TABLE gSmmSystemTable; +#endif +#if SMM_USE_PI +extern EFI_SMM_SYSTEM_TABLE2 gSmmSystemTable2; +extern EFI_SMM_ENTRY_CONTEXT gEfiSmmEntryContext; //For now, hardcode. +#endif +extern SMM_DISPATCHER_PRIVATE_STRUCT *gDispatcherPrivate; + +#if SMM_USE_PI +EFI_STATUS SmmMemRead( + IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This, + IN EFI_SMM_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer +); + +EFI_STATUS SmmMemWrite( + IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This, + IN EFI_SMM_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer +); + +EFI_STATUS SmmIoRead( + IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This, + IN EFI_SMM_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer +); + +EFI_STATUS SmmIoWrite( + IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This, + IN EFI_SMM_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer +); + +EFI_STATUS SmmSmstAllocatePages( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN NumberOfPages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory +); + +EFI_STATUS SmmSmstFreePages( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages +); + +EFI_STATUS SmmStartupThisAp( + IN EFI_AP_PROCEDURE Procedure, + IN UINTN CpuNumber, + IN OUT VOID *ProcArguments OPTIONAL +); + +#endif + +EFI_STATUS SmmSmstAllocatePool( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer +); + +EFI_STATUS SmmSmstFreePool( + IN VOID *Buffer +); + +EFI_STATUS CalculateCrc32( + IN VOID *Data, IN UINTN DataSize, OUT UINT32 *Crc32 +); + +#if SMM_USE_PI + +EFI_STATUS SmmInstallConfigurationTable( + IN EFI_SMM_SYSTEM_TABLE2 *SystemTable, + IN EFI_GUID *Guid, + IN VOID *Table, + IN UINTN TableSize + ); + +EFI_STATUS ReadSaveState( + IN CONST EFI_SMM_CPU_PROTOCOL *This, + IN UINTN Width, + IN EFI_SMM_SAVE_STATE_REGISTER Register, + IN UINTN CpuIndex, + OUT VOID *Buffer +) +{ + UINT8 *SmmBase; +#if SMM_USE_FRAMEWORK + UINT8 *SstSaveState; +#endif + + if (CpuIndex >= gDispatcherPrivate->NumCpus) return EFI_INVALID_PARAMETER; + + SmmBase = gSmmBase[CpuIndex]; +#if SMM_USE_FRAMEWORK + SstSaveState = (UINT8*)&gSmmSystemTable.CpuSaveState[CpuIndex]; +#endif + + if (Register >= EFI_SMM_SAVE_STATE_REGISTER_FCW && Register <= EFI_SMM_SAVE_STATE_REGISTER_XMM15) { + return CpuLib_SmmReadSaveStateFxSave( + gDispatcherPrivate->SmmXmmSave[CpuIndex], + (UINT8)Width, + Register, + (VOID*)Buffer + ); + } + + return CPULib_SmmReadSaveState( + SmmBase, +#if SMM_USE_FRAMEWORK + SstSaveState, + TRUE, +#else + NULL, + FALSE, +#endif + (UINT8)Width, + Register, + Buffer + ); +} + +EFI_STATUS WriteSaveState( + IN CONST EFI_SMM_CPU_PROTOCOL *This, + IN UINTN Width, + IN EFI_SMM_SAVE_STATE_REGISTER Register, + IN UINTN CpuIndex, + IN CONST VOID *Buffer +) +{ + UINT8 *SmmBase; +#if SMM_USE_FRAMEWORK + UINT8 *SstSaveState; +#endif + + if (CpuIndex >= gDispatcherPrivate->NumCpus) return EFI_INVALID_PARAMETER; + + SmmBase = gSmmBase[CpuIndex]; +#if SMM_USE_FRAMEWORK + SstSaveState = (UINT8*)&gSmmSystemTable.CpuSaveState[CpuIndex]; +#endif + + if (Register >= EFI_SMM_SAVE_STATE_REGISTER_FCW && Register <= EFI_SMM_SAVE_STATE_REGISTER_XMM15) { + return CpuLib_SmmWriteSaveStateFxSave( + gDispatcherPrivate->SmmXmmSave[CpuIndex], + (UINT8)Width, + Register, + (VOID*)Buffer + ); + } + + return CPULib_SmmWriteSaveState( + SmmBase, +#if SMM_USE_FRAMEWORK + SstSaveState, + TRUE, +#else + NULL, + FALSE, +#endif + (UINT8)Width, + Register, + Buffer + ); +} + +EFI_SMM_CPU_PROTOCOL gEfiSmmCpuProtocol = { + ReadSaveState, + WriteSaveState +}; + + +static EFI_LIST_ENTRY SmmProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (SmmProtocolDatabase); +EFI_LIST_ENTRY SmmHandleList = INITIALIZE_LIST_HEAD_VARIABLE (SmmHandleList); +UINTN mEfiLocateHandleRequest = 0; // Added for SmmSmstLocateProtocol + +EFI_LIST_ENTRY mRootSmiHandlerList = INITIALIZE_LIST_HEAD_VARIABLE (mRootSmiHandlerList); +EFI_LIST_ENTRY mSmiEntryList = INITIALIZE_LIST_HEAD_VARIABLE (mSmiEntryList); + +SMM_IHANDLE *SmmGetNextLocateByRegisterNotify( + IN OUT SMM_LOCATE_POSITION *Position, + OUT VOID **Interface +); + + +SMM_IHANDLE *SmmGetNextLocateByProtocol ( + IN OUT SMM_LOCATE_POSITION *Position, + OUT VOID **Interface +); + +SMM_IHANDLE *SmmGetNextLocateAllHandles ( + IN OUT SMM_LOCATE_POSITION *Position, + OUT VOID **Interface +); + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmValidateHandle +// +// Description: Check whether a handle is a valid EFI_HANDLE. +// +// Input: +// IN EFI_HANDLE UserHandle + +// Output: +// EFI_STATUS +//---------------------------------------------------------------------------- +// + +EFI_STATUS +SmmValidateHandle ( + IN EFI_HANDLE UserHandle +) +{ + SMM_IHANDLE *Handle; + Handle = (SMM_IHANDLE *)UserHandle; + if (Handle == NULL) { + return EFI_INVALID_PARAMETER; + } + if (Handle->Signature != SMM_EFI_HANDLE_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmFindProtocolEntry +// +// Description: Finds the protocol entry for the requested protocol. +// +// Input: +// IN EFI_GUID *Protocol +// IN BOOLEAN Create +// +// Output: +// Protocol entry +//---------------------------------------------------------------------------- +// +SMM_PROTOCOL_ENTRY * +SmmFindProtocolEntry ( + IN EFI_GUID *Protocol, + IN BOOLEAN Create + ) +{ + EFI_LIST_ENTRY *Link; + SMM_PROTOCOL_ENTRY *Item; + SMM_PROTOCOL_ENTRY *ProtEntry; + EFI_STATUS Status; + // + // Search the database for the matching GUID + // + + ProtEntry = NULL; + for (Link = SmmProtocolDatabase.ForwardLink; + Link != &SmmProtocolDatabase; + Link = Link->ForwardLink + ) { + Item = CR(Link, SMM_PROTOCOL_ENTRY, AllEntries, SMM_PROTOCOL_ENTRY_SIGNATURE); + if ( !guidcmp (&Item->ProtocolID, Protocol)) { + // + // This is the protocol entry + // + ProtEntry = Item; + break; + } + } + + // + // If the protocol entry was not found and Create is TRUE, then + // allocate a new entry + // + if ((ProtEntry == NULL) && Create) { + Status = SmmSmstAllocatePool(0,sizeof(SMM_PROTOCOL_ENTRY),&ProtEntry); // ********** Probe whether it works? Typecast to VOID** to make it go thro SmmPiAllocatePool. + if (ProtEntry != NULL) { + // + // Initialize new protocol entry structure + // + ProtEntry->Signature = SMM_PROTOCOL_ENTRY_SIGNATURE; + ProtEntry->ProtocolID = *Protocol; // This done as Core Handle.C function implementation. + InitializeListHead (&ProtEntry->Protocols); + InitializeListHead (&ProtEntry->Notify); + + // + // Add it to protocol database + // + InsertTailList (&SmmProtocolDatabase, &ProtEntry->AllEntries); + } + } + return ProtEntry; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmFindProtocolInterface +// +// Description: +// Finds the protocol instance for the requested handle and protocol. +// Note: This function doesn't do parameters checking, it's caller's responsibility +// to pass in valid parameters. +// +// Input: +// IN SMM_IHANDLE *Handle, +// IN EFI_GUID *Protocol +// IN VOID *Interface +// +// Output: +// Protocol instance (NULL: Not found) +//---------------------------------------------------------------------------- +// + +SMM_PROTOCOL_INTERFACE * SmmFindProtocolInterface ( + IN SMM_IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +{ + SMM_PROTOCOL_INTERFACE *Prot; + SMM_PROTOCOL_ENTRY *ProtEntry; + EFI_LIST_ENTRY *Link; + + Prot = NULL; + + // + // Lookup the protocol entry for this protocol ID + // + ProtEntry = SmmFindProtocolEntry (Protocol, FALSE); + if (ProtEntry != NULL) { + // + // Look at each protocol interface for any matches + // + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) { + // + // If this protocol interface matches, remove it + // + Prot = CR(Link, SMM_PROTOCOL_INTERFACE, Link, SMM_PROTOCOL_INTERFACE_SIGNATURE); + if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) { + break; + } + Prot = NULL; + } + } + return Prot; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmNotifyProtocol +// +// Description: Signal event for every protocol in protocol entry. +// +// Input: +// IN SMM_PROTOCOL_INTERFACE *Prot + +// Output: +// VOID +//---------------------------------------------------------------------------- +// + +VOID SmmNotifyProtocol ( + IN SMM_PROTOCOL_INTERFACE *Prot + ) +{ + SMM_PROTOCOL_ENTRY *ProtEntry; + SMM_PROTOCOL_NOTIFY *ProtNotify; + EFI_LIST_ENTRY *Link; + + ProtEntry = Prot->Protocol; + for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { + ProtNotify = CR(Link, SMM_PROTOCOL_NOTIFY, Link, SMM_PROTOCOL_NOTIFY_SIGNATURE); + ProtNotify->Function (&ProtEntry->ProtocolID, Prot->Interface, Prot->Handle); + } +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmSmstInstallProtocolInterface +// +// Description: +// Wrapper function to SmmInstallProtocolInterfaceNotify. This is the public API which +// Calls the private one which contains a BOOLEAN parameter for notifications +// +// Input: +// IN OUT EFI_HANDLE *Handle +// IN EFI_GUID *Protocol +// IN EFI_INTERFACE_TYPE InterfaceType +// IN VOID Interface +// +// Output: EFI_STATUS +//--------------------------------------------------------------------------- +// + +EFI_STATUS SmmSmstInstallProtocolInterface ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface +) +{ + return SmmSmstInstallProtocolInterfaceNotify ( + UserHandle, + Protocol, + InterfaceType, + Interface, + TRUE + ); +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmSmstInstallProtocolInterfaceNotify +// +// Description: Installs a protocol interface into the boot services environment. + +// Input: +// IN OUT EFI_HANDLE *UserHandle, +// IN EFI_GUID *Protocol, +// IN EFI_INTERFACE_TYPE InterfaceType, +// IN VOID *Interface, +// IN BOOLEAN Notify +// +// Output: EFI_STATUS +//--------------------------------------------------------------------------- +// + +EFI_STATUS +SmmSmstInstallProtocolInterfaceNotify ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface, + IN BOOLEAN Notify +) +{ + SMM_PROTOCOL_INTERFACE *Prot; + SMM_PROTOCOL_ENTRY *ProtEntry; + SMM_IHANDLE *Handle; + EFI_STATUS Status; + VOID *ExistingInterface; + + // + // returns EFI_INVALID_PARAMETER if InterfaceType is invalid. + // Also added check for invalid UserHandle and Protocol pointers. + // + + if (UserHandle == NULL || Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (InterfaceType != EFI_NATIVE_INTERFACE) { + return EFI_INVALID_PARAMETER; + } + + // + // Print debug message + // + //DEBUG((DEBUG_LOAD | DEBUG_INFO, "SmmInstallProtocolInterface: %g %p\n", Protocol, Interface)); + + Status = EFI_OUT_OF_RESOURCES; + + Prot = NULL; + Handle = NULL; + + if (*UserHandle != NULL) { + Status = SmmSmstHandleProtocol(*UserHandle, Protocol, (VOID **)&ExistingInterface); + + if (!EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Lookup the Protocol Entry for the requested protocol + // + ProtEntry = SmmFindProtocolEntry (Protocol, TRUE); + + if (ProtEntry == NULL) { + goto Done; + } + + // + // Allocate a new protocol interface structure + // + Status = SmmSmstAllocatePool(0,sizeof(SMM_PROTOCOL_INTERFACE),&Prot); + MemSet(Prot,(Prot == NULL) ? 0 : sizeof(SMM_PROTOCOL_INTERFACE), 0); + + if (Prot == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // If caller didn't supply a handle, allocate a new one + // + Handle = (SMM_IHANDLE *)*UserHandle; + if (Handle == NULL) { + Status = SmmSmstAllocatePool(0,sizeof(SMM_IHANDLE),&Handle); + MemSet(Handle,(Handle == NULL) ? 0 : sizeof(SMM_IHANDLE), 0); + if (Handle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Initialize new handler structure + // + Handle->Signature = SMM_EFI_HANDLE_SIGNATURE; + InitializeListHead (&Handle->Protocols); + + // + // Add this handle to the list global list of all handles + // in the system + // + InsertTailList (&SmmHandleList, &Handle->AllHandles); + } + + Status = SmmValidateHandle (Handle); + + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Each interface that is added must be unique + // + ASSERT (SmmFindProtocolInterface (Handle, Protocol, Interface) == NULL); + + // + // Initialize the protocol interface structure + // + Prot->Signature = SMM_PROTOCOL_INTERFACE_SIGNATURE; + Prot->Handle = Handle; + Prot->Protocol = ProtEntry; + Prot->Interface = Interface; + + // + // Add this protocol interface to the head of the supported + // protocol list for this handle + // + InsertHeadList (&Handle->Protocols, &Prot->Link); + + // + // Add this protocol interface to the tail of the + // protocol entry + // + InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol); + + // + // Notify the notification list for this protocol + // + if (Notify) { + SmmNotifyProtocol (Prot); + } + Status = EFI_SUCCESS; + +Done: + if (!EFI_ERROR (Status)) { + // + // Return the new handle back to the caller + // + *UserHandle = Handle; + } else { + // + // There was an error, clean up + // + if (Prot != NULL) { + SmmSmstFreePool (Prot); + } + } + return Status; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmSmstUninstallProtocolInterface +// +// Description: +// Uninstalls all instances of a protocol:interfacer from a handle. +// If the last protocol interface is remove from the handle, the +// handle is freed. +// +// Input: +// IN OUT EFI_HANDLE UserHandle +// IN EFI_GUID *Protocol +// IN VOID *Interface +// +// Output: EFI_STATUS +//--------------------------------------------------------------------------- +// + +EFI_STATUS SmmSmstUninstallProtocolInterface ( + IN OUT EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN VOID *Interface +) +{ + EFI_STATUS Status; + SMM_IHANDLE *Handle; + SMM_PROTOCOL_INTERFACE *Prot; + + // + // Check that Protocol is valid + // + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check that UserHandle is a valid handle + // + Status = SmmValidateHandle (UserHandle); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check that Protocol exists on UserHandle, and Interface matches the interface in the database + // + Prot = SmmFindProtocolInterface (UserHandle, Protocol, Interface); + + if (Prot == NULL) { + return EFI_NOT_FOUND; + } + + // + // Remove the protocol interface from the protocol + // + Status = EFI_NOT_FOUND; + Handle = (SMM_IHANDLE *)UserHandle; + + Prot = SmmRemoveInterfaceFromProtocol (Handle, Protocol, Interface); + + if (Prot != NULL) { + // + // Remove the protocol interface from the handle + // + RemoveEntryList (&Prot->Link); + + // + // Free the memory + // + Prot->Signature = 0; + SmmSmstFreePool(Prot); + Status = EFI_SUCCESS; + } + + // + // If there are no more handlers for the handle, free the handle + // + if (IsListEmpty (&Handle->Protocols)) { + Handle->Signature = 0; + RemoveEntryList (&Handle->AllHandles); + SmmSmstFreePool (Handle); + } + return Status; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmRemoveInterfaceFromProtocol +// +// Description: Removes Protocol from the protocol list (but not the handle list). +// +// Input: +// IN SMM_IHANDLE *Handle, +// IN EFI_GUID *Protocol +// IN VOID *Interface +// +// Output: Protocol Entry +//--------------------------------------------------------------------------- +// + +SMM_PROTOCOL_INTERFACE * SmmRemoveInterfaceFromProtocol ( + IN SMM_IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface +) +{ + SMM_PROTOCOL_INTERFACE *Prot; + SMM_PROTOCOL_NOTIFY *ProtNotify; + SMM_PROTOCOL_ENTRY *ProtEntry; + EFI_LIST_ENTRY *Link; + + Prot = SmmFindProtocolInterface (Handle, Protocol, Interface); + if (Prot != NULL) { + ProtEntry = Prot->Protocol; + + // + // If there's a protocol notify location pointing to this entry, back it up one + // + for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { + ProtNotify = CR(Link, SMM_PROTOCOL_NOTIFY, Link, SMM_PROTOCOL_NOTIFY_SIGNATURE); + + if (ProtNotify->Position == &Prot->ByProtocol) { + ProtNotify->Position = Prot->ByProtocol.BackLink; + } + } + + // + // Remove the protocol interface entry + // + RemoveEntryList (&Prot->ByProtocol); + } + + return Prot; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmGetProtocolInterface +// +// Description: Locate a certain GUID protocol interface in a Handle's protocols. +// +// Input: +// IN EFI_HANDLE UserHandle, +// IN EFI_GUID *Protocol +// +// Output: +// The requested protocol interface for the handle. +//--------------------------------------------------------------------------- +// + +SMM_PROTOCOL_INTERFACE * SmmGetProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol +) +{ + EFI_STATUS Status; + SMM_PROTOCOL_ENTRY *ProtEntry; + SMM_PROTOCOL_INTERFACE *Prot; + SMM_IHANDLE *Handle; + EFI_LIST_ENTRY *Link; + + Status = SmmValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return NULL; + } + + Handle = (SMM_IHANDLE *)UserHandle; + + // + // Look at each protocol interface for a match + // + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, SMM_PROTOCOL_INTERFACE, Link, SMM_PROTOCOL_INTERFACE_SIGNATURE); + ProtEntry = Prot->Protocol; + if (!guidcmp(&ProtEntry->ProtocolID, Protocol)) { + return Prot; + } + } + return NULL; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmSmstHandleProtocol +// +// Description: Queries a handle to determine if it supports a specified protocol. +// +// Input: +// IN OUT EFI_HANDLE UserHandle +// IN EFI_GUID *Protocol +// OUT VOID **Interface +// +// Output: +// EFI_STATUS +//--------------------------------------------------------------------------- +// + +EFI_STATUS SmmSmstHandleProtocol ( + IN OUT EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT VOID **Interface +) +{ + EFI_STATUS Status; + SMM_PROTOCOL_INTERFACE *Prot; + + // + // Check for invalid Protocol + // + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check for invalid Interface + // + if (Interface == NULL) { + return EFI_INVALID_PARAMETER; + } else { + *Interface = NULL; + } + + // + // Check for invalid UserHandle + // + Status = SmmValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Look at each protocol interface for a match + // + Prot = SmmGetProtocolInterface (UserHandle, Protocol); + if (Prot == NULL) { + return EFI_UNSUPPORTED; + } + + // + // This is the protocol interface entry for this protocol + // + *Interface = Prot->Interface; + + return EFI_SUCCESS; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmSmstRegisterProtocolNotify +// +// Description: Add a new protocol notification record for the request protocol. +// +// Input: +// IN EFI_GUID *Protocol +// IN EFI_SMM_NOTIFY_FN Function +// OUT VOID **Registration +// +// Output: +// EFI_STATUS +//--------------------------------------------------------------------------- +// + +EFI_STATUS SmmSmstRegisterProtocolNotify ( + IN CONST EFI_GUID *Protocol, + IN EFI_SMM_NOTIFY_FN Function, + OUT VOID **Registration) +{ + SMM_PROTOCOL_ENTRY *ProtEntry=NULL; + SMM_PROTOCOL_NOTIFY *ProtNotify=NULL; + EFI_LIST_ENTRY *Link; +// EFI_GUID *protocol=(EFI_GUID*)Protocol; + EFI_STATUS Status; + + if ((Protocol == NULL) || (Function == NULL) || (Registration == NULL)) { + return EFI_INVALID_PARAMETER; + } + + ProtNotify = NULL; + + // + // Get the protocol entry to add the notification too + // + ProtEntry = SmmFindProtocolEntry ((EFI_GUID *) Protocol, TRUE); + if (ProtEntry != NULL) { + // + // Find whether notification already exist + // + for (Link = ProtEntry->Notify.ForwardLink; + Link != &ProtEntry->Notify; + Link = Link->ForwardLink) { + + ProtNotify = CR(Link, SMM_PROTOCOL_NOTIFY, Link, SMM_PROTOCOL_NOTIFY_SIGNATURE); + if ((!guidcmp(&ProtNotify->Protocol->ProtocolID, (EFI_GUID*)Protocol)) && + (ProtNotify->Function == Function) + ) { + + // + // Notification already exist + // + *Registration = ProtNotify; + + return EFI_SUCCESS; + } + } + + // + // Allocate a new notification record + // + Status = SmmSmstAllocatePool(0,sizeof(SMM_PROTOCOL_NOTIFY),&ProtNotify); + ASSERT_EFI_ERROR(Status); + if (ProtNotify != NULL) { + ProtNotify->Signature = SMM_PROTOCOL_NOTIFY_SIGNATURE; + ProtNotify->Protocol = ProtEntry; + ProtNotify->Function = Function; + // + // Start at the ending + // + ProtNotify->Position = ProtEntry->Protocols.BackLink; + + InsertTailList (&ProtEntry->Notify, &ProtNotify->Link); + } + } + + // + // Done. If we have a protocol notify entry, then return it. + // Otherwise, we must have run out of resources trying to add one + // + Status = EFI_OUT_OF_RESOURCES; + if (ProtNotify != NULL) { + *Registration = ProtNotify; + Status = EFI_SUCCESS; + } + return Status; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmSmstLocateHandle +// +// Description: Locates the requested handle(s) and returns them in Buffer. +// +// Input: +// IN EFI_LOCATE_SEARCH_TYPE SearchType +// IN EFI_GUID *Protocol OPTIONAL +// IN VOID *SearchKey OPTIONAL +// IN OUT UINTN *BufferSize +// OUT EFI_HANDLE *Buffer +// +// Output: +// EFI_STATUS +//--------------------------------------------------------------------------- +// +EFI_STATUS SmmSmstLocateHandle ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *BufferSize, + OUT EFI_HANDLE *Buffer +) + +{ + EFI_STATUS Status; + SMM_LOCATE_POSITION Position; + SMM_PROTOCOL_NOTIFY *ProtNotify; + SMM_CORE_GET_NEXT GetNext; + UINTN ResultSize; + SMM_IHANDLE *Handle; + SMM_IHANDLE **ResultBuffer; + VOID *Interface; + + if (BufferSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((*BufferSize > 0) && (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + GetNext = NULL; + + // + // Set initial position + // + Position.Protocol = Protocol; + Position.SearchKey = SearchKey; + Position.Position = &SmmHandleList; + + ResultSize = 0; + ResultBuffer = (SMM_IHANDLE **) Buffer; + Status = EFI_SUCCESS; + + // + // Get the search function based on type + // + switch (SearchType) { + case AllHandles: + GetNext = SmmGetNextLocateAllHandles; + break; + + case ByRegisterNotify: + GetNext = SmmGetNextLocateByRegisterNotify; + // + // Must have SearchKey for locate ByRegisterNotify + // + if (SearchKey == NULL) { + Status = EFI_INVALID_PARAMETER; + } + break; + case ByProtocol: + GetNext = SmmGetNextLocateByProtocol; + if (Protocol == NULL) { + Status = EFI_INVALID_PARAMETER; + break; + } + // + // Look up the protocol entry and set the head pointer + // + Position.ProtEntry = SmmFindProtocolEntry (Protocol, FALSE); + if (Position.ProtEntry == NULL) { + Status = EFI_NOT_FOUND; + break; + } + Position.Position = &Position.ProtEntry->Protocols; + break; + default: + Status = EFI_INVALID_PARAMETER; + break; + } + + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Enumerate out the matching handles + // + mEfiLocateHandleRequest += 1; + for (; ;) { + // + // Get the next handle. If no more handles, stop + // + Handle = GetNext (&Position, &Interface); + if (NULL == Handle) { + break; + } + + // + // Increase the resulting buffer size, and if this handle + // fits return it + // + ResultSize += sizeof(Handle); + if (ResultSize <= *BufferSize) { + *ResultBuffer = Handle; + ResultBuffer += 1; + } + } + + // + // If the result is a zero length buffer, then there were no + // matching handles + // + if (ResultSize == 0) { + Status = EFI_NOT_FOUND; + } else { + // + // Return the resulting buffer size. If it's larger than what + // was passed, then set the error code + // + if (ResultSize > *BufferSize) { + Status = EFI_BUFFER_TOO_SMALL; + } + + *BufferSize = ResultSize; + + if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) { + ASSERT (SearchKey != NULL); + // + // If this is a search by register notify and a handle was + // returned, update the register notification position + // + ProtNotify = SearchKey; + ProtNotify->Position = ProtNotify->Position->ForwardLink; + } + } + return Status; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmSmstLocateProtocol +// +// Description: +// Return the first Protocol Interface that matches the Protocol GUID. If +// Registration is passed in, return a Protocol Instance that was just add +// to the system. If Registration is NULL return the first Protocol Interface +// you find. +// +// Input: +// IN EFI_GUID *Protocol, +// IN VOID *Registration OPTIONAL +// OUT VOID **Interface +// +// Output: +// EFI_STATUS +//--------------------------------------------------------------------------- +// + +EFI_STATUS SmmSmstLocateProtocol ( + IN EFI_GUID *Protocol, + IN VOID *Registration OPTIONAL, + OUT VOID **Interface +) +{ + EFI_STATUS Status; + SMM_LOCATE_POSITION Position; + SMM_PROTOCOL_NOTIFY *ProtNotify; + SMM_IHANDLE *Handle; + + if (Interface == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Protocol == NULL) { + return EFI_NOT_FOUND; + } + + *Interface = NULL; + Status = EFI_SUCCESS; + // + // Set initial position + // + Position.Protocol = Protocol; + Position.SearchKey = Registration; + Position.Position = &SmmHandleList; + + mEfiLocateHandleRequest += 1; + + if (Registration == NULL) { + // + // Look up the protocol entry and set the head pointer + // + Position.ProtEntry = SmmFindProtocolEntry (Protocol, FALSE); + if (Position.ProtEntry == NULL) { + return EFI_NOT_FOUND; + } + Position.Position = &Position.ProtEntry->Protocols; + + Handle = SmmGetNextLocateByProtocol (&Position, Interface); + } else { + Handle = SmmGetNextLocateByRegisterNotify (&Position, Interface); + } + + if (Handle == NULL) { + Status = EFI_NOT_FOUND; + } else if (Registration != NULL) { + // + // If this is a search by register notify and a handle was + // returned, update the register notification position + // + ProtNotify = Registration; + ProtNotify->Position = ProtNotify->Position->ForwardLink; + } + + return Status; +} + + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmGetNextLocateAllHandles +// +// Description: +// Find next handle. +// +// Input: +// IN OUT SMM_LOCATE_POSITION *Position, +// OUT VOID **Interface +// +// Output: +// SMM_IHANDLE +//--------------------------------------------------------------------------- +// + +SMM_IHANDLE *SmmGetNextLocateAllHandles ( + IN OUT SMM_LOCATE_POSITION *Position, + OUT VOID **Interface +) +{ + SMM_IHANDLE *Handle; + + // + // Next handle + // + Position->Position = Position->Position->ForwardLink; + + // + // If not at the end of the list, get the handle + // + Handle = NULL; + *Interface = NULL; + if (Position->Position != &SmmHandleList) { + Handle = CR (Position->Position, SMM_IHANDLE, AllHandles, SMM_EFI_HANDLE_SIGNATURE); + } + return Handle; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmGetNextLocateByRegisterNotify +// +// Description: Routine to get the next Handle, when you are searching for register protocol +// notifies. +// +// Input: +// IN OUT SMM_LOCATE_POSITION *Position +// OUT VOID **Interface +// +// Output: +// An pointer to SMM_IHANDLE if the next Position is not the end of the list. +// Otherwise,NULL is returned. +//--------------------------------------------------------------------------- +// + +SMM_IHANDLE *SmmGetNextLocateByRegisterNotify ( + IN OUT SMM_LOCATE_POSITION *Position, + OUT VOID **Interface +) +{ + SMM_IHANDLE *Handle; + SMM_PROTOCOL_NOTIFY *ProtNotify; + SMM_PROTOCOL_INTERFACE *Prot; + EFI_LIST_ENTRY *Link; + + Handle = NULL; + *Interface = NULL; + ProtNotify = Position->SearchKey; + + // + // If this is the first request, get the next handle + // + if (ProtNotify != NULL) { + ASSERT(ProtNotify->Signature == SMM_PROTOCOL_NOTIFY_SIGNATURE); + Position->SearchKey = NULL; + + // + // If not at the end of the list, get the next handle + // + Link = ProtNotify->Position->ForwardLink; + if (Link != &ProtNotify->Protocol->Protocols) { + Prot = CR (Link, SMM_PROTOCOL_INTERFACE, ByProtocol, SMM_PROTOCOL_INTERFACE_SIGNATURE); + Handle = Prot->Handle; + *Interface = Prot->Interface; + } + } + return Handle; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmGetNextLocateByProtocol +// +// Description: Routine to get the next Handle, when you are searching for a given protocol. +// +// Input: +// IN OUT SMM_LOCATE_POSITION *Position +// OUT VOID **Interface +// +// Output: +// An pointer to SMM_IHANDLE if the next Position is not the end of the list. +// Otherwise,NULL is returned. +//--------------------------------------------------------------------------- +// + +SMM_IHANDLE *SmmGetNextLocateByProtocol ( + IN OUT SMM_LOCATE_POSITION *Position, + OUT VOID **Interface +) +{ + SMM_IHANDLE *Handle; + EFI_LIST_ENTRY *Link; + SMM_PROTOCOL_INTERFACE *Prot; + + Handle = NULL; + *Interface = NULL; + + for (; ;) { + // + // Next entry + // + Link = Position->Position->ForwardLink; + Position->Position = Link; + + // + // If not at the end, return the handle + // + if (Link == &Position->ProtEntry->Protocols) { + Handle = NULL; + break; + } + + // + // Get the handle + // + Prot = CR(Link, SMM_PROTOCOL_INTERFACE, ByProtocol, SMM_PROTOCOL_INTERFACE_SIGNATURE); + Handle = Prot->Handle; + *Interface = Prot->Interface; + + // + // If this handle has not been returned this request, then + // return it now + // + if (Handle->LocateRequest != mEfiLocateHandleRequest) { + Handle->LocateRequest = mEfiLocateHandleRequest; + break; + } + } + return Handle; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmmCoreFindSmiEntry +// +// Description: Find Smi Entry +// +// Input: +// IN EFI_GUID *HandlerType +// IN BOOLEAN Create +// +// Output: SMM_SMI_ENTRY +//--------------------------------------------------------------------------- +// + +SMM_SMI_ENTRY* SmmCoreFindSmiEntry ( + IN EFI_GUID *HandlerType, + IN BOOLEAN Create +) +{ + EFI_LIST_ENTRY *Link; + SMM_SMI_ENTRY *Item; + SMM_SMI_ENTRY *SmiEntry; + EFI_STATUS Status; + + // + // Search the SMI entry list for the matching GUID + // + SmiEntry = NULL; + for (Link = mSmiEntryList.ForwardLink; + Link != &mSmiEntryList; + Link = Link->ForwardLink) { + + Item = CR (Link, SMM_SMI_ENTRY, AllEntries, SMI_ENTRY_SIGNATURE); + if (!guidcmp(&Item->HandlerType, HandlerType)) { + // + // This is the SMI entry + // + SmiEntry = Item; + break; + } + } + + // + // If the protocol entry was not found and Create is TRUE, then + // allocate a new entry + // + if ((SmiEntry == NULL) && Create) { + Status = SmmSmstAllocatePool (0,sizeof(SMM_SMI_ENTRY),&SmiEntry); + if (EFI_ERROR(Status) || (SmiEntry != NULL)) { + // + // Initialize new SMI entry structure + // + SmiEntry->Signature = SMI_ENTRY_SIGNATURE; + MemCpy((VOID *)&SmiEntry->HandlerType, HandlerType, sizeof(EFI_GUID)); + InitializeListHead (&SmiEntry->SmiHandlers); + + // Add it to SMI entry list + InsertTailList (&mSmiEntryList, &SmiEntry->AllEntries); + } + } + return SmiEntry; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: SmiHandlerRegister +// +// Description: Register SMI Handle +// +// Input: +// IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler, +// IN CONST EFI_GUID *HandlerType OPTIONAL, +// OUT EFI_HANDLE *DispatchHandle +// +// Output: EFI_STATUS +//--------------------------------------------------------------------------- +// + +EFI_STATUS SmiHandlerRegister( + IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler, + IN CONST EFI_GUID *HandlerType OPTIONAL, + OUT EFI_HANDLE *DispatchHandle +) +{ + HANDLER_LIST *HandlerInfo, *Link; + + if (gSmmSystemTable2.SmmAllocatePool(0, sizeof(HANDLER_LIST), &HandlerInfo) != EFI_SUCCESS) + return EFI_OUT_OF_RESOURCES; + + HandlerInfo->IsPi = TRUE; + HandlerInfo->EntryPoint = Handler; + HandlerInfo->SmmImageHandle = HandlerInfo; + if (HandlerType) { + MemCpy(&HandlerInfo->HandlerType, (EFI_GUID*)HandlerType, sizeof(EFI_GUID)); + HandlerInfo->IsRoot = FALSE; + } else HandlerInfo->IsRoot = TRUE; + + HandlerInfo->Link = 0; + + //If very first add. + if (!gDispatcherPrivate->HandlerListHead) { + gDispatcherPrivate->HandlerListHead = HandlerInfo; + return EFI_SUCCESS; + } + + //Add to end of list. + for (Link = gDispatcherPrivate->HandlerListHead; Link->Link; Link = Link->Link); //Find end of list + Link->Link = HandlerInfo; + + return EFI_SUCCESS; +} + +EFI_STATUS SmiHandlerUnRegister(IN EFI_HANDLE DispatchHandle) +{ + HANDLER_LIST *Link = gDispatcherPrivate->HandlerListHead; + HANDLER_LIST *PrevLink; + + while (Link != 0) { + if (Link->SmmImageHandle == DispatchHandle) { + if (Link == gDispatcherPrivate->HandlerListHead) { + gDispatcherPrivate->HandlerListHead = Link->Link; + } else { + PrevLink->Link = Link->Link; + } + SmmSmstFreePool(Link); + return EFI_SUCCESS; + } + PrevLink = Link; + Link = Link->Link; + } + return EFI_INVALID_PARAMETER; +} + +EFI_SMM_SYSTEM_TABLE2 gSmmSystemTable2 = +{ + { //Header + SMM_SMST_SIGNATURE2, //Signature + EFI_SMM_SYSTEM_TABLE_REVISION2, //Revison will show 1.1 + sizeof(EFI_SMM_SYSTEM_TABLE2), //Header size + 0, //CRC32 + 0 //Reserved + }, + gSmmFirmwareVendor, //Vendor + 0, //Vendor version + + SmmInstallConfigurationTable, + { + { + SmmMemRead, + SmmMemWrite + }, + { + SmmIoRead, + SmmIoWrite + } + }, + SmmSmstAllocatePool, + SmmSmstFreePool, + SmmSmstAllocatePages, + SmmSmstFreePages, + SmmStartupThisAp, + 1, //Executing CPU + 1, //Number of CPUs + 0, //CpuSaveStateSize...PI 1.1 + 0, //Cpu Save State + 0, //Number of Table Entries + 0, //Table pointer + SmmSmstInstallProtocolInterface, + SmmSmstUninstallProtocolInterface, + SmmSmstHandleProtocol, + SmmSmstRegisterProtocolNotify, + SmmSmstLocateHandle, + SmmSmstLocateProtocol, + InterruptManage, + SmiHandlerRegister, + SmiHandlerUnRegister +}; + +// +//--------------------------------------------------------------------------- +// +// Procedure: InsertTailList +// +// Description: +// Insert a Node into the end of a doubly linked list. The list must have +// been initialized with InitializeListHead () before using this function. +// +// +// Input: +// IN EFI_LIST_ENTRY *ListHead +// IN EFI_LIST_ENTRY *Entry +// +// Output: VOID +//--------------------------------------------------------------------------- +// + +VOID InsertTailList ( + IN EFI_LIST_ENTRY *ListHead, + IN EFI_LIST_ENTRY *Entry +) +{ + EFI_LIST_ENTRY *_ListHead; + EFI_LIST_ENTRY *_BackLink; + + _ListHead = ListHead; + _BackLink = _ListHead->BackLink; + Entry->ForwardLink = _ListHead; + Entry->BackLink = _BackLink; + _BackLink->ForwardLink = Entry; + _ListHead->BackLink = Entry; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: InsertHeadList +// +// Description: +// Insert a Node into the start of a doubly linked list. The list must have +// been initialized with InitializeListHead () before using this function. +// +// Input: +// IN EFI_LIST_ENTRY *ListHead +// IN EFI_LIST_ENTRY *Entry +// +// Output: VOID +//--------------------------------------------------------------------------- +// + +VOID InsertHeadList ( + IN EFI_LIST_ENTRY *ListHead, + IN EFI_LIST_ENTRY *Entry +) +{ + EFI_LIST_ENTRY *_ListHead; + EFI_LIST_ENTRY *_ForwardLink; + + _ListHead = ListHead; + _ForwardLink = _ListHead->ForwardLink; + Entry->ForwardLink = _ForwardLink; + Entry->BackLink = _ListHead; + _ForwardLink->BackLink = Entry; + _ListHead->ForwardLink = Entry; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: InitializeListHead +// +// Description: +// Initialize the head of the List. The caller must allocate the memory +// for the EFI_LIST. This function must be called before the other linked +// list macros can be used. +// +// Input: +// IN EFI_LIST_ENTRY *List +// +// Output: VOID +//--------------------------------------------------------------------------- +// + +VOID InitializeListHead ( + IN EFI_LIST_ENTRY *List +) +{ + List->ForwardLink = List; + List->BackLink = List; +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: IsListEmpty +// +// Description: +// Return TRUE is the list contains zero nodes. Otherwise return FALSE. +// The list must have been initialized with InitializeListHead () before using +// this function. +// +// Input: +// IN EFI_LIST_ENTRY *List +// +// Output: VOID +//--------------------------------------------------------------------------- +// + +BOOLEAN IsListEmpty ( + IN EFI_LIST_ENTRY *List +) +{ + return (BOOLEAN)(List->ForwardLink == List); +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: RemoveEntryList +// +// Description: +// Remove Node from the doubly linked list. It is the caller's responsibility +// to free any memory used by the entry if needed. The list must have been +// initialized with InitializeListHead () before using this function. +// +// Input: +// IN EFI_LIST_ENTRY *Entry +// +// Output: VOID +//--------------------------------------------------------------------------- +// + +VOID RemoveEntryList ( + EFI_LIST_ENTRY *Entry +) +{ + EFI_LIST_ENTRY *_ForwardLink; + EFI_LIST_ENTRY *_BackLink; + + _ForwardLink = Entry->ForwardLink; + _BackLink = Entry->BackLink; + _BackLink->ForwardLink = _ForwardLink; + _ForwardLink->BackLink = _BackLink; + +#if EFI_DEBUG + Entry->ForwardLink = (EFI_LIST_ENTRY *) 0xAFAFAFAF; + Entry->BackLink = (EFI_LIST_ENTRY *) 0xAFAFAFAF; +#endif +} + +// +//--------------------------------------------------------------------------- +// +// Procedure: InitializeSmmPiSystemTable +// +// Description: +// Initialize SMM PI System Table. +// +// Input: VOID +// +// Output: VOID +//--------------------------------------------------------------------------- +// + +VOID InitializeSmmPiSystemTable() +{ + UINT32 CRC32; + UINT32 NumCpus = gDispatcherPrivate->NumCpus; + UINT32 i; + + gSmmSystemTable2.NumberOfCpus = NumCpus; + + gSmmSystemTable2.CpuSaveStateSize = Allocate(0,sizeof(UINTN) * NumCpus,0); + for (i = 0; i < NumCpus; ++i) gSmmSystemTable2.CpuSaveStateSize[i] = MAX_SMM_SAVE_STATE_SIZE; + + gSmmSystemTable2.CpuSaveState = Allocate(0,sizeof(VOID*) * NumCpus,0); + for (i = 0; i < NumCpus; ++i) { + gSmmSystemTable2.CpuSaveState[i] = (VOID*)(gSmmBase[i] + 0x10000 - MAX_SMM_SAVE_STATE_SIZE); + } + + CalculateCrc32(&gSmmSystemTable2, sizeof(EFI_SMM_SYSTEM_TABLE2), &CRC32); + gSmmSystemTable2.Hdr.CRC32 = CRC32; + + gEfiSmmEntryContext.SmmStartupThisAp = gSmmSystemTable2.SmmStartupThisAp; + gEfiSmmEntryContext.NumberOfCpus = gSmmSystemTable2.NumberOfCpus; + gEfiSmmEntryContext.CpuSaveStateSize = gSmmSystemTable2.CpuSaveStateSize; + gEfiSmmEntryContext.CpuSaveState = gSmmSystemTable2.CpuSaveState; +} +#endif + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* -- cgit v1.2.3