diff options
Diffstat (limited to 'Core/EM/SMM/Smst.c')
-rw-r--r-- | Core/EM/SMM/Smst.c | 917 |
1 files changed, 917 insertions, 0 deletions
diff --git a/Core/EM/SMM/Smst.c b/Core/EM/SMM/Smst.c new file mode 100644 index 0000000..8ac8add --- /dev/null +++ b/Core/EM/SMM/Smst.c @@ -0,0 +1,917 @@ +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* + +//********************************************************************** +// $Header: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/SMM/Smst.c 2 11/21/12 4:07a Wesleychen $ +// +// $Revision: 2 $ +// +// $Date: 11/21/12 4:07a $ +//********************************************************************** +// Revision History +// ---------------- +// $Log: /Alaska/Projects/Intel/Haswell/LynxPoint_SharkBay-DT_Crb_1AQQW/Core/EM/SMM/Smst.c $ +// +// 2 11/21/12 4:07a Wesleychen +// Support Intel PFAT. +// +// 25 3/14/11 3:18p Markw +// Rename gSmmFirmwareVender to gSmmFirmwareVendor. +// +// 24 2/07/11 3:29p 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 +// +// 23 6/18/10 12:29p Markw +// Fix history log. +// +// 22 4/22/10 6:22p Markw +// Support /w4 compilier option. +// +// 21 2/25/10 5:16p Markw +// Add support for all APs to execute non-blocking. +// Fixed issue with memory allocation +// +// 20 2/12/10 3:54p Markw +// Update SmmSmstAllocatePages for AllocateAddress to return correct +// Status. +// +// 19 5/08/09 10:55a Markw +// Header updates. +// +// 18 11/05/08 5:25p Markw +// Fix SMM Allocate Pool of type AllocateMaxAddress. +// +// 17 9/09/08 4:30p Markw +// Add headers. +// +// 16 9/07/08 12:45a Markw +// Separate SMM Private structure into inside SMM and outside SMM +// structure. Remove access to BS function for CRC. +// +// 15 6/09/08 5:47p Markw +// CPU0 has its own AP control structure. CPU0 can now be the AP. +// +// 14 3/14/07 5:57p Markw +// Only allow SmmStartupThisAp if all CPUs are in SMM. +// +//********************************************************************** + +//<AMI_FHDR_START> +//--------------------------------------------------------------------------- +// +// Name: Smst.c +// +// Description: Smst functions. +// +//--------------------------------------------------------------------------- +//<AMI_FHDR_END> + +//This include should come first. +#include "SmmPrivateShared.h" +#include <AmiDxeLib.h> +#include <AmiCspLib.h> + +#if SMM_USE_FRAMEWORK +#include <Smm.h> +#endif + +#if SMM_USE_PI +#include <SmmPi.h> +#endif + +#include "ReferenceCode\Haswell\Include\CpuRegs.h" +#ifndef BIT35 +#define BIT35 0x0000000800000000ULL +#endif + +//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); + +UINT8* Align2n(UINT8 *Value,UINTN Alignment); + +#if SMM_USE_FRAMEWORK + +EFI_STATUS CalculateCrc32( + IN VOID *Data, IN UINTN DataSize, OUT UINT32 *Crc32 +); + +extern EFI_SMM_SYSTEM_TABLE gSmmSystemTable; +extern UINT8 **gSmmBase; +#endif + +#if SMM_USE_PI +extern EFI_SMM_SYSTEM_TABLE2 gSmmSystemTable2; +#endif + + +extern SMM_DISPATCHER_PRIVATE_STRUCT *gDispatcherPrivate; + +static UINT32 CrcTable[256]; + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: InitCrc +// +// Description: InitCrc +// +// Input: VOID +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID InitCrc() +{ + UINT32 i, j; + for(i = 0; i < 256; i++) { + CrcTable[i] = i; + for(j = 8; j > 0; j--) + CrcTable[i] = + (CrcTable[i] & 1) ? (CrcTable[i] >> 1) ^ 0xedb88320 : CrcTable[i] >> 1; + } +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: CalculateCrc32 +// +// Description: Calculate Crc 32 +// +// Input: +// IN VOID *Data +// IN UINTN DataSize +// OUT UINT32 *Crc32 +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS CalculateCrc32( + IN VOID *Data, IN UINTN DataSize, OUT UINT32 *Crc32 +) +{ + UINT32 i, crc = (UINT32)-1; + if (!Data || !DataSize || !Crc32) return EFI_INVALID_PARAMETER; + for(i = 0; i < DataSize; i++) crc = (crc >> 8) ^ CrcTable[(UINT8)crc ^ ((UINT8*)Data)[i]]; + *Crc32 = ~crc; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SmmMemRead +// +// Description: Read memory buffer. +// +// Input: +// IN EFI_SMM_CPU_IO_INTERFACE *This +// IN EFI_SMM_IO_WIDTH Width +// IN UINT64 Address +// IN UINTN Count +// IN OUT VOID *Buffer +// +// Output: +// EFI_STATUS +// * EFI_SUCCESS - Buffer written Successfully. +// * EFI_INVALID_PARAMETER - 0 Count, Unsupported Width, or memory region out of range. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmmMemRead( + IN EFI_SMM_CPU_IO_INTERFACE *This, + IN EFI_SMM_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer +) +{ + UINT8 ByteWidth; + if (Width >= (UINTN)SMM_IO_UINT64) return EFI_INVALID_PARAMETER; + if (!Count) return EFI_INVALID_PARAMETER; + + ByteWidth = (UINT8)(1 << Width); + + + //Alignment must be done by the caller. + switch(ByteWidth) { + case 1: + while(Count--) { + *(UINT8*)Buffer = *(UINT8*)(UINTN)Address; + ++((UINT8*)(UINTN)Buffer); + ++((UINT8*)(UINTN)Address); + } + break; + case 2: + while(Count--) { + *(UINT16*)Buffer = *(UINT16*)(UINTN)Address; + ++((UINT16*)(UINTN)Buffer); + ++((UINT16*)(UINTN)Address); + } + break; + default: //case 4: + while(Count--) { + *(UINT32*)Buffer = *(UINT32*)(UINTN)Address; + ++((UINT32*)(UINTN)Buffer); + ++((UINT32*)(UINTN)Address); + } + break; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SmmMemWrite +// +// Description: Write to memory from buffer. +// +// Input: +// IN EFI_SMM_CPU_IO_INTERFACE *This +// IN EFI_SMM_IO_WIDTH Width +// IN UINT64 Address +// IN UINTN Count +// IN OUT VOID *Buffer +// +// Output: +// EFI_STATUS +// * EFI_SUCCESS - Buffer written Successfully. +// * EFI_INVALID_PARAMETER - 0 Count, Unsupported Width, or memory region out of range. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmmMemWrite( + IN EFI_SMM_CPU_IO_INTERFACE *This, + IN EFI_SMM_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + UINT8 ByteWidth; + if (Width >= (UINTN)SMM_IO_UINT64) return EFI_INVALID_PARAMETER; + if (!Count) return EFI_INVALID_PARAMETER; + + //Alignment must be done by the caller. + ByteWidth = (UINT8)(1 << Width); + + switch(ByteWidth) { + case 1: + while(Count--) { + *(UINT8*)(UINTN)Address = *(UINT8*)(UINTN)Buffer; + ++((UINT8*)(UINTN)Buffer); + ++((UINT8*)(UINTN)Address); + } + break; + case 2: + while(Count--) { + *(UINT16*)(UINTN)Address = *(UINT16*)(UINTN)Buffer; + ++((UINT16*)(UINTN)Buffer); + ++((UINT16*)(UINTN)Address); + } + break; + default: //case 4: + while(Count--) { + *(UINT32*)(UINTN)Address = *(UINT32*)(UINTN)Buffer; + ++((UINT32*)(UINTN)Buffer); + ++((UINT32*)(UINTN)Address); + } + break; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SmmIoRead +// +// Description: Read io buffer. +// +// Input: +// IN EFI_SMM_CPU_IO_INTERFACE *This +// IN EFI_SMM_IO_WIDTH Width +// IN UINT64 Address +// IN UINTN Count +// IN OUT VOID *Buffer +// +// Output: +// EFI_STATUS +// * EFI_SUCCESS - Buffer written Successfully. +// * EFI_INVALID_PARAMETER - 0 Count, Unsupported Width, or memory region out of range. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmmIoRead( + IN EFI_SMM_CPU_IO_INTERFACE *This, + IN EFI_SMM_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + UINT8 ByteWidth; + if (Width >= (UINTN)SMM_IO_UINT64) return EFI_INVALID_PARAMETER; + if (!Count) return EFI_INVALID_PARAMETER; + + ByteWidth = (UINT8)(1 << Width); + + if (Address + ByteWidth * Count > 0x10000) return EFI_INVALID_PARAMETER; //Beyond IO space. + if ((UINT64)(UINTN)Buffer + ByteWidth * Count > (UINT64)0x100000000) return EFI_INVALID_PARAMETER; //Beyond address space. + + //Alignment must be done by the caller. + switch(ByteWidth) { + case 1: + while(Count--) { + *(UINT8*)Buffer = IoRead8((UINT16)Address); + ++((UINT8*)(UINTN)Buffer); + ++((UINT8*)(UINTN)Address); + } + break; + case 2: + while(Count--) { + *(UINT16*)(UINTN)Buffer = IoRead16((UINT16)Address); + ++((UINT16*)(UINTN)Buffer); + ++((UINT16*)(UINTN)Address); + } + break; + default: //case 4: + while(Count--) { + *(UINT32*)Buffer = IoRead32((UINT16)Address); + ++((UINT32*)(UINTN)Buffer); + ++((UINT32*)(UINTN)Address); + } + break; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SmmIoWrite +// +// Description: Write to Io from buffer. +// +// Input: +// IN EFI_SMM_CPU_IO_INTERFACE *This +// IN EFI_SMM_IO_WIDTH Width +// IN UINT64 Address +// IN UINTN Count +// IN OUT VOID *Buffer +// +// Output: +// EFI_STATUS +// * EFI_SUCCESS - Buffer written Successfully. +// * EFI_INVALID_PARAMETER - 0 Count, Unsupported Width, or memory region out of range. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmmIoWrite( + IN EFI_SMM_CPU_IO_INTERFACE *This, + IN EFI_SMM_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +{ + UINT8 ByteWidth; + if (Width >= (UINTN)SMM_IO_UINT64) return EFI_INVALID_PARAMETER; + if (!Count) return EFI_INVALID_PARAMETER; + + ByteWidth = (UINT8)(1 << Width); + + if (Address + ByteWidth * Count > 0x10000) return EFI_INVALID_PARAMETER; //Beyond IO space. + if ((UINT64)(UINTN)Buffer + ByteWidth * Count > (UINT64)0x100000000) return EFI_INVALID_PARAMETER; //Beyond address space. + + //Alignment must be done by the caller. + switch(ByteWidth) { + case 1: + while(Count--) { + IoWrite8((UINT16)Address,*(UINT8*)(UINTN)Buffer); + ++((UINT8*)(UINTN)Buffer); + ++((UINT8*)(UINTN)Address); + } + break; + case 2: + while(Count--) { + IoWrite16((UINT16)Address,*(UINT16*)(UINTN)Buffer); + ++((UINT16*)(UINTN)Buffer); + ++((UINT16*)(UINTN)Address); + } + break; + default: //case 4: + while(Count--) { + IoWrite32((UINT16)Address,*(UINT32*)(UINTN)Buffer); + ++((UINT32*)(UINTN)Buffer); + ++((UINT32*)(UINTN)Address); + } + break; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SmmSmstAllocatePool +// +// Description: Allocate a pool of memory. +// +// Input: +// IN EFI_MEMORY_TYPE PoolType +// IN UINTN Size +// OUT VOID **Buffer +// +// Output: +// EFI_STATUS +// * EFI_SUCCESS - Pool of memory allocated. +// * EFI_INVALID_PARAMETER - Allocate 0 size. +// * EFI_OUT_OF_RESOURCES - Memory unavailable. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmmSmstAllocatePool( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ) +{ + if (!Size) return EFI_INVALID_PARAMETER; + *Buffer = Allocate(0,Size,0); + if (!(*Buffer)) return EFI_OUT_OF_RESOURCES; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SmmSmstFreePool +// +// Description: Free Allocated memory. +// +// Input: +// IN VOID *Buffer +// +// Output: +// EFI_STATUS +// * EFI_SUCCESS - Memory is freed. +// * EFI_INVALID_PARAMETER - Memory starting at Buffer was not allocated. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmmSmstFreePool( + IN VOID *Buffer + ) +{ + if (!Free(Buffer)) return EFI_INVALID_PARAMETER; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SmmSmstAllocatePages +// +// Description: Allocate # pages at any address, a max address, or a specified address. +// +// Input: +// IN EFI_ALLOCATE_TYPE Type +// IN EFI_MEMORY_TYPE MemoryType +// IN UINTN NumberOfPages +// OUT EFI_PHYSICAL_ADDRESS *Memory +// +// Output: +// EFI_STATUS +// * EFI_SUCCESS - Memory allocated. +// * EFI_OUT_OF_RESOURCES - Memory already allocated or unavailable. +// * EFI_INVALID_PARAMETER - Incorrect Type or specified address not 4k aligned. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmmSmstAllocatePages( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN NumberOfPages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ) +{ + VOID *AllocatedMemory; + + if (!NumberOfPages) return EFI_INVALID_PARAMETER; + if (Type != AllocateAnyPages && *Memory <= 0x100000) return AllocateABSegPages(Type, NumberOfPages, Memory); + + switch(Type) { + case AllocateAnyPages: + *Memory = (EFI_PHYSICAL_ADDRESS)(UINTN)Allocate(0, NumberOfPages * 4096, 4095); + if (!(*Memory)) return EFI_OUT_OF_RESOURCES; + return EFI_SUCCESS; + + case AllocateMaxAddress: + AllocatedMemory = Allocate(0, NumberOfPages * 4096, 4095); + if (!AllocatedMemory) return EFI_OUT_OF_RESOURCES; + if ((UINTN)AllocatedMemory > *(UINTN*)(UINTN)Memory) { + Free(AllocatedMemory); + return EFI_OUT_OF_RESOURCES; + } + *Memory = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatedMemory; + return EFI_SUCCESS; + case AllocateAddress: + if ((UINT8*)(UINTN)*Memory != Align2n((UINT8*)(UINTN)*Memory,4095)) return EFI_INVALID_PARAMETER; + AllocatedMemory = Allocate((UINT8*)(UINTN)*Memory,NumberOfPages * 4096,0); + if (!AllocatedMemory) return EFI_OUT_OF_RESOURCES; + return EFI_SUCCESS; + } + return EFI_INVALID_PARAMETER; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SmmSmstFreePages +// +// Description: +// Free pages. The address must be on a page boundary, but it doesn't have to +// start on address from AllocatePages. It only frees the requested pages. +// +// Input: +// IN EFI_PHYSICAL_ADDRESS Memory +// IN UINTN NumberOfPages +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmmSmstFreePages( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages + ) +{ + if (Memory <= 0x100000) return FreeABSegPages(Memory, NumberOfPages); + + if (!Free4kPages((VOID*)(UINTN)Memory,NumberOfPages)) return EFI_INVALID_PARAMETER; + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SmmStartupThisAp +// +// Description: Execute a procedure on an AP. +// +// Input: +// IN EFI_AP_PROCEDURE Procedure +// IN UINTN CpuNumber +// IN OUT VOID *ProcArguments OPTIONAL +// +// Output: +// EFI_STATUS +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmmStartupThisAp( + IN EFI_AP_PROCEDURE Procedure, + IN UINTN CpuNumber, + IN OUT VOID *ProcArguments OPTIONAL +) +{ + volatile SMM_AP_CPU_CONTROL *SmmApCpuControl; + BOOLEAN IsBlocking = (BOOLEAN)(CpuNumber != (UINTN)-1); + UINT32 i; + + if (Procedure == NULL) return EFI_INVALID_PARAMETER; + if (CpuNumber == gDispatcherPrivate->SmmBspNumber) return EFI_INVALID_PARAMETER; + if (CpuNumber >= gDispatcherPrivate->NumCpus && IsBlocking) return EFI_INVALID_PARAMETER; + + if (IsBlocking) { + if (!gDispatcherPrivate->SmmCpuInfo[CpuNumber].InSmm) return EFI_NOT_READY; + SmmApCpuControl = &gDispatcherPrivate->SmmApCpuControl[CpuNumber]; + + SmmApCpuControl->ProcArguments = ProcArguments; + SmmApCpuControl->Procedure = Procedure; + + if ( !((ReadMsr (MSR_PLATFORM_INFO) & B_MSR_PLATFORM_INFO_PFAT_AVAIL) && + (ReadMsr (MSR_PLAT_FRMW_PROT_CTRL) & B_MSR_PLAT_FRMW_PROT_CTRL_EN)) ) { + while(SmmApCpuControl->Procedure) CPULib_Pause(); + } + return EFI_SUCCESS; + } + + for (i = 0; i < gDispatcherPrivate->NumCpus; ++i) { + if (i == gDispatcherPrivate->SmmBspNumber) continue; + if (!gDispatcherPrivate->SmmCpuInfo[i].InSmm) continue; + SmmApCpuControl = &gDispatcherPrivate->SmmApCpuControl[i]; + ASSERT(SmmApCpuControl->Procedure == NULL); + if (SmmApCpuControl->Procedure != NULL) continue; + + SmmApCpuControl->ProcArguments = ProcArguments; + SmmApCpuControl->Procedure = Procedure; + } + + return EFI_SUCCESS; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: MoveToNewConfigurationTable +// +// Description: Create a new bigger or smaller table and copy the old table to the new table. +// +// Input: +// IN EFI_CONFIGURATION_TABLE *OldTable +// IN UINTN NumOldDescriptors +// IN UINTN NumDescriptors +// +// Output: +// EFI_CONFIGURATION_TABLE * - New table address. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_CONFIGURATION_TABLE * MoveToNewConfigurationTable( + EFI_CONFIGURATION_TABLE *OldTable, + UINTN NumOldDescriptors, + UINTN NumDescriptors + ) +{ + EFI_CONFIGURATION_TABLE *NewTable,*Descriptor,*OldDescriptor; + UINTN i; + //Create new table + if (SmmSmstAllocatePool(0,NumDescriptors * sizeof(EFI_CONFIGURATION_TABLE),&NewTable)!=EFI_SUCCESS) return 0; + + //If new table is larger, only copy valid descriptors. + //If new table is smaller, only copy descriptors for allocated table. + NumDescriptors = NumDescriptors > NumOldDescriptors ? NumOldDescriptors : NumDescriptors; + Descriptor = NewTable; + OldDescriptor = OldTable; + for (i=0;i<NumDescriptors;++i) *Descriptor++ = *OldDescriptor++; + + //Free old table + SmmSmstFreePool(OldTable); + + return NewTable; +} + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: SmmInstallConfigurationTable +// +// Description: +// This procedure add/updates/deletes configuration table entries. +// +// Configuration Table Entry definition: +// EFI_GUID VendorGuid +// VOID *VenderTable +// +// 1. If Vendor Guid is not in table and Input table isn't NULL, add Guid/Table pair. +// 2. If Vendor Guid is in table and Input table isn't NULL, update Guid/Table pair. +// 3. If Vendor Guid is in table and Input table is NULL, remove Guid/Tablble pair. +// 4. If Vendor Guid is not in table, Input table is NULL, return EFI_NOT_FOUND. Nothing to delete. +// +// Input: +// IN EFI_SMM_SYSTEM_TABLE *SystemTable +// IN EFI_GUID *Guid +// IN VOID *Table +// IN UINTN TableSize +// +// Output: +// EFI_STATUS +// * EFI_SUCCESS - Add/update/remove operation successful. +// * EFI_INVALID_PARAMETER - Guid = 0. +// * EFI_NOT_FOUND - Can not delete a nonexistent entry. +// * EFI_OUT_OF_RESOURCES - Not enough memory to complete operation. +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +EFI_STATUS SmmInstallConfigurationTable( +#if SMM_USE_FRAMEWORK + IN EFI_SMM_SYSTEM_TABLE *SystemTable, +#else + IN EFI_SMM_SYSTEM_TABLE2 *SystemTable, +#endif + IN EFI_GUID *Guid, + IN VOID *Table, + IN UINTN TableSize + ) +{ + UINTN i; + UINT32 CRC32; + +#if SMM_USE_PI + EFI_CONFIGURATION_TABLE **FirstEntryPtr = &gSmmSystemTable2.SmmConfigurationTable; + EFI_CONFIGURATION_TABLE *Entry = *FirstEntryPtr; + UINTN *NumberOfTableEntries = &gSmmSystemTable2.NumberOfTableEntries; + UINT32 SystemTableSize = sizeof(gSmmSystemTable2); + #else + EFI_CONFIGURATION_TABLE **FirstEntryPtr = &gSmmSystemTable.SmmConfigurationTable; + EFI_CONFIGURATION_TABLE *Entry = *FirstEntryPtr; + UINTN *NumberOfTableEntries = &gSmmSystemTable.NumberOfTableEntries; + UINT32 SystemTableSize = sizeof(gSmmSystemTable); +#endif + + EFI_CONFIGURATION_TABLE *NewConfigTable; + VOID *NewVendorTable; + + if (!Guid) return EFI_INVALID_PARAMETER; + + for (i=0;i < *NumberOfTableEntries;++i) { + if (guidcmp(&Entry->VendorGuid,Guid)==0) break; + ++Entry; + } + if (i == *NumberOfTableEntries) Entry=0; + + if (!Entry) { + if (!Table) return EFI_NOT_FOUND; + //Add Guid + NewConfigTable = MoveToNewConfigurationTable( + *FirstEntryPtr, + *NumberOfTableEntries, + *NumberOfTableEntries+1); + if (!NewConfigTable) return EFI_OUT_OF_RESOURCES; + + if (SmmSmstAllocatePool(0,TableSize,&NewVendorTable)!=EFI_SUCCESS) return EFI_OUT_OF_RESOURCES; + MemCpy(NewVendorTable,Table,TableSize); + *FirstEntryPtr = NewConfigTable; + ++(*NumberOfTableEntries); + NewConfigTable[*NumberOfTableEntries - 1].VendorGuid = *Guid; + NewConfigTable[*NumberOfTableEntries - 1].VendorTable = NewVendorTable; + } else { + if (!Table) { + //Remove Guid + EFI_CONFIGURATION_TABLE *LastEntry = *FirstEntryPtr + *NumberOfTableEntries; + + SmmSmstFreePool(Entry->VendorTable); + + while (Entry != LastEntry) { + *Entry = *(Entry + 1); + ++Entry; + } + + --(*NumberOfTableEntries); + } else { + //Update Guid + if (SmmSmstAllocatePool(0,TableSize,&NewVendorTable)!=EFI_SUCCESS) return EFI_OUT_OF_RESOURCES; + MemCpy(NewVendorTable,Table,TableSize); + + SmmSmstFreePool(Entry->VendorTable); + Entry->VendorTable = NewVendorTable; + } + } + +#if SMM_USE_PI && SMM_USE_FRAMEWORK + gSmmSystemTable.SmmConfigurationTable = gSmmSystemTable2.SmmConfigurationTable; + gSmmSystemTable.NumberOfTableEntries = gSmmSystemTable2.NumberOfTableEntries; +#endif + +#if SMM_USE_PI + gSmmSystemTable2.Hdr.CRC32 = 0; + CalculateCrc32(&gSmmSystemTable2, SystemTableSize, &CRC32); + gSmmSystemTable2.Hdr.CRC32 = CRC32; +#endif + +#if SMM_USE_FRAMEWORK + gSmmSystemTable.Hdr.CRC32 = 0; + CalculateCrc32(&gSmmSystemTable, sizeof(EFI_SMM_SYSTEM_TABLE), &CRC32); + gSmmSystemTable.Hdr.CRC32 = CRC32; +#endif + + return EFI_SUCCESS; +} + + +#if SMM_USE_FRAMEWORK + +////////////////////////////////////////// +extern CHAR16 gSmmFirmwareVendor[]; +EFI_SMM_SYSTEM_TABLE gSmmSystemTable = +{ + { //Header + SMM_SMST_SIGNATURE, //Signature + EFI_SMM_SYSTEM_TABLE_REVISION, //Revision + sizeof(EFI_SMM_SYSTEM_TABLE), //Header size + 0, //CRC32 + 0 //Reserved + }, + gSmmFirmwareVendor, //Vendor + 0, //Vendor version + SmmInstallConfigurationTable, + EFI_SMM_CPU_IO_GUID, + { + { + SmmMemRead, + SmmMemWrite + }, + { SmmIoRead, + SmmIoWrite + } + }, + SmmSmstAllocatePool, + SmmSmstFreePool, + SmmSmstAllocatePages, + SmmSmstFreePages, + SmmStartupThisAp, + 1, //Executing CPU + 1, //Number of CPUs + 0, //Cpu Save State + 0, //Cpu Floating Point Save + 0, //Number of Table Entries + 0 //Table pointer +}; + + +//<AMI_PHDR_START> +//--------------------------------------------------------------------------- +// +// Procedure: InitializeSmmSystemTable +// +// Description: Initialize the System Table. +// +// Input: SMM_BASE_PRIVATE_STRUCT *Private +// +// Output: VOID +// +//--------------------------------------------------------------------------- +//<AMI_PHDR_END> + +VOID InitializeSmmSystemTable() +{ + UINT32 CRC32; + + gSmmSystemTable.NumberOfCpus = gDispatcherPrivate->NumCpus; + + gSmmSystemTable.CpuSaveState = Allocate(0,sizeof(EFI_SMM_CPU_SAVE_STATE) * gSmmSystemTable.NumberOfCpus,0); + gSmmSystemTable.CpuOptionalFloatingPointState = Allocate(0, 512 * gSmmSystemTable.NumberOfCpus, 15); //16 byte alignment, Save floating point context. + + CalculateCrc32(&gSmmSystemTable, sizeof(EFI_SMM_SYSTEM_TABLE), &CRC32); + gSmmSystemTable.Hdr.CRC32 = CRC32; +} + +#endif + +//************************************************************************* +//************************************************************************* +//** ** +//** (C)Copyright 1985-2011, American Megatrends, Inc. ** +//** ** +//** All Rights Reserved. ** +//** ** +//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +//** ** +//** Phone: (770)-246-8600 ** +//** ** +//************************************************************************* +//************************************************************************* |