blob: 3d7cf51eeeb9e7b355140c1e2293bf5fd8a3cb1b [file] [log] [blame]
/** @file
CPU Configuration Library.
Copyright (c) 2013 Intel Corporation.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Intel Corporation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Module Name: CpuConfig.c
**/
#include "CpuConfig.h"
CPU_CONFIG_CONTEXT_BUFFER *mCpuConfigLibConfigConextBuffer;
/**
The constructor function of CPU Configuration Library.
The constructor function caches the value of PCD entry PcdCpuConfigContextBuffer.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
**/
EFI_STATUS
EFIAPI
CpuConfigLibConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
//
// Get the pointer to CPU Configuration Context Buffer from PcdCpuConfigContextBuffer.
// This PCD entry is set by CPU driver.
//
mCpuConfigLibConfigConextBuffer = (CPU_CONFIG_CONTEXT_BUFFER *) (UINTN) PcdGet64 (PcdCpuConfigContextBuffer);
return EFI_SUCCESS;
}
/**
Set feature capability and related attribute.
This function sets the feature capability and its attribute.
@param ProcessorNumber Handle number of specified logical processor
@param FeatureID The ID of the feature.
@param Attribute Feature-specific data.
**/
VOID
EFIAPI
SetProcessorFeatureCapability (
IN UINTN ProcessorNumber,
IN CPU_FEATURE_ID FeatureID,
IN VOID *Attribute
)
{
CPU_COLLECTED_DATA *CpuCollectedData;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
CpuCollectedData = &mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber];
//
// Set the feature capability of the specified processor as TRUE,
// and set feature-specified attribute for the feature.
//
CpuCollectedData->FeatureData[FeatureID].Capability = TRUE;
CpuCollectedData->FeatureData[FeatureID].Attribute = Attribute;
}
/**
Clears feature capability and related attribute.
This function clears the feature capability and its attribute.
@param ProcessorNumber Handle number of specified logical processor
@param FeatureID The ID of the feature.
**/
VOID
EFIAPI
ClearProcessorFeatureCapability (
IN UINTN ProcessorNumber,
IN CPU_FEATURE_ID FeatureID
)
{
CPU_COLLECTED_DATA *CpuCollectedData;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
CpuCollectedData = &mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber];
//
// Set the feature capability of the specified processor as FALSE,
// and clears feature-specified attribute for the feature.
//
CpuCollectedData->FeatureData[FeatureID].Capability = FALSE;
CpuCollectedData->FeatureData[FeatureID].Attribute = NULL;
}
/**
Get feature capability and related attribute.
This function gets the feature capability and its attribute.
@param ProcessorNumber Handle number of specified logical processor
@param FeatureID The ID of the feature.
@param Attribute Pointer to the output feature-specific data.
@retval TRUE The feature is supported by the processor
@retval FALSE The feature is not supported by the processor
**/
BOOLEAN
EFIAPI
GetProcessorFeatureCapability (
IN UINTN ProcessorNumber,
IN CPU_FEATURE_ID FeatureID,
OUT VOID **Attribute OPTIONAL
)
{
CPU_COLLECTED_DATA *CpuCollectedData;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
CpuCollectedData = &mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber];
//
// If Attribute is not NULL, set feature-specified attribute to it.
//
if (Attribute != NULL) {
*Attribute = CpuCollectedData->FeatureData[FeatureID].Attribute;
}
return CpuCollectedData->FeatureData[FeatureID].Capability;
}
/**
Get the number of CPUID leafs of various types.
This function get the number of CPUID leafs of various types.
@param ProcessorNumber Handle number of specified logical processor
@param CpuidType The type of the cpu id.
@return Maximal index of CPUID instruction for basic leafs.
**/
UINTN
EFIAPI
GetNumberOfCpuidLeafs (
IN UINTN ProcessorNumber,
IN CPUID_TYPE CpuidType
)
{
UINTN NumberOfLeafs;
CPU_CPUID_DATA *CpuidData;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
CpuidData = &(mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber].CpuidData);
switch (CpuidType) {
case BasicCpuidLeaf:
NumberOfLeafs = CpuidData->NumberOfBasicCpuidLeafs;
break;
case ExtendedCpuidLeaf:
NumberOfLeafs = CpuidData->NumberOfExtendedCpuidLeafs;
break;
case CacheAndTlbCpuidLeafs:
NumberOfLeafs = CpuidData->NumberOfCacheAndTlbCpuidLeafs;
break;
case DeterministicCacheParametersCpuidLeafs:
NumberOfLeafs = CpuidData->NumberOfDeterministicCacheParametersCpuidLeafs;
break;
case ExtendedTopologyEnumerationCpuidLeafs:
NumberOfLeafs = CpuidData->NumberOfExtendedTopologyEnumerationLeafs;
break;
default:
NumberOfLeafs = 0;
break;
}
return NumberOfLeafs;
}
/**
Get the pointer to specified CPUID leaf.
This function gets the pointer to specified CPUID leaf.
@param ProcessorNumber Handle number of specified logical processor
@param Index Index of the CPUID leaf.
@return Pointer to specified CPUID leaf
**/
EFI_CPUID_REGISTER*
EFIAPI
GetProcessorCpuid (
IN UINTN ProcessorNumber,
IN UINTN Index
)
{
CPU_CPUID_DATA *CpuidData;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
CpuidData = &(mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber].CpuidData);
//
// If Index specifies basic CPUID leafs, then locate basic leaf to return.
//
if (Index < CpuidData->NumberOfBasicCpuidLeafs) {
return (&CpuidData->CpuIdLeaf[Index]);
}
//
// If Index specifies extended CPUID leafs, then locate extended leaf to return.
//
if (Index >= 0x80000000 && Index < 0x80000000 + CpuidData->NumberOfExtendedCpuidLeafs) {
return (&CpuidData->CpuIdLeaf[Index - 0x80000000 + CpuidData->NumberOfBasicCpuidLeafs]);
}
//
// If Index specifies invalid CPUID index, then return NULL.
//
return NULL;
}
/**
Get the pointer to specified CPUID leaf of cache and TLB parameters.
This function gets the pointer to specified CPUID leaf of cache and TLB parameters.
@param ProcessorNumber Handle number of specified logical processor
@param Index Index of the CPUID leaf.
@return Pointer to specified CPUID leaf.
**/
EFI_CPUID_REGISTER*
EFIAPI
GetCacheAndTlbCpuidLeaf (
IN UINTN ProcessorNumber,
IN UINTN Index
)
{
UINTN StartIndex;
CPU_CPUID_DATA *CpuidData;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
CpuidData = &(mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber].CpuidData);
//
// The first leaf resides in basic leaf 2
//
if (Index == 0) {
return (&CpuidData->CpuIdLeaf[2]);
}
//
// If index is greater than zero, calculate the start index of deterministic cache CPUID leafs.
//
StartIndex = CpuidData->NumberOfBasicCpuidLeafs + CpuidData->NumberOfExtendedCpuidLeafs;
return (&CpuidData->CpuIdLeaf[Index + StartIndex - 1]);
}
/**
Get the pointer to specified CPUID leaf of deterministic cache parameters.
This function gets the pointer to specified CPUID leaf of deterministic cache parameters.
@param ProcessorNumber Handle number of specified logical processor
@param Index Index of the CPUID leaf.
@return Pointer to specified CPUID leaf.
**/
EFI_CPUID_REGISTER*
EFIAPI
GetDeterministicCacheParametersCpuidLeaf (
IN UINTN ProcessorNumber,
IN UINTN Index
)
{
UINTN StartIndex;
CPU_CPUID_DATA *CpuidData;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
CpuidData = &(mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber].CpuidData);
//
// Calculate the start index of deterministic cache CPUID leafs.
//
StartIndex = CpuidData->NumberOfBasicCpuidLeafs;
StartIndex += CpuidData->NumberOfExtendedCpuidLeafs;
StartIndex += CpuidData->NumberOfCacheAndTlbCpuidLeafs - 1;
return (&CpuidData->CpuIdLeaf[Index + StartIndex]);
}
/**
Get the pointer to specified CPUID leaf of Extended Topology Enumeration.
This function gets the pointer to specified CPUID leaf of Extended Topology Enumeration.
@param ProcessorNumber Handle number of specified logical processor.
@param Index Index of the CPUID leaf.
@return Pointer to specified CPUID leaf.
**/
EFI_CPUID_REGISTER*
EFIAPI
GetExtendedTopologyEnumerationCpuidLeafs (
IN UINTN ProcessorNumber,
IN UINTN Index
)
{
UINTN StartIndex;
CPU_CPUID_DATA *CpuidData;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
CpuidData = &(mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber].CpuidData);
//
// Calculate the start index of Extended Topology Enumeration CPUID leafs.
//
StartIndex = CpuidData->NumberOfBasicCpuidLeafs;
StartIndex += CpuidData->NumberOfExtendedCpuidLeafs;
StartIndex += CpuidData->NumberOfCacheAndTlbCpuidLeafs - 1;
StartIndex += CpuidData->NumberOfDeterministicCacheParametersCpuidLeafs;
return (&CpuidData->CpuIdLeaf[Index + StartIndex]);
}
/**
Get the version information of specified logical processor.
This function gets the version information of specified logical processor,
including family ID, model ID, stepping ID and processor type.
@param ProcessorNumber Handle number of specified logical processor
@param DisplayedFamily Pointer to family ID for output
@param DisplayedModel Pointer to model ID for output
@param SteppingId Pointer to stepping ID for output
@param ProcessorType Pointer to processor type for output
**/
VOID
EFIAPI
GetProcessorVersionInfo (
IN UINTN ProcessorNumber,
OUT UINT32 *DisplayedFamily OPTIONAL,
OUT UINT32 *DisplayedModel OPTIONAL,
OUT UINT32 *SteppingId OPTIONAL,
OUT UINT32 *ProcessorType OPTIONAL
)
{
EFI_CPUID_REGISTER *VersionInfo;
UINT32 RegEax;
UINT32 FamilyId;
UINT32 ExtendedFamilyId;
UINT32 ExtendedModelId;
//
// Get CPUID(1).EAX
//
VersionInfo = GetProcessorCpuid (ProcessorNumber, EFI_CPUID_VERSION_INFO);
ASSERT (VersionInfo != NULL);
RegEax = VersionInfo->RegEax;
//
// Processor Type is CPUID(1).EAX[12:13]
//
if (ProcessorType != NULL) {
*ProcessorType = BitFieldRead32 (RegEax, 12, 13);
}
//
// Stepping ID is CPUID(1).EAX[0:3]
//
if (SteppingId != NULL) {
*SteppingId = BitFieldRead32 (RegEax, 0, 3);
}
//
// The Extended Family ID needs to be examined only when the Family ID is 0FH.
// If Family ID is 0FH, Displayed Family ID = Family ID + Extended Family ID.
// Otherwise, Displayed Family ID is Family ID
//
FamilyId = BitFieldRead32 (RegEax, 8, 11);
if (DisplayedFamily != NULL) {
*DisplayedFamily = FamilyId;
if (FamilyId == 0x0f) {
ExtendedFamilyId = BitFieldRead32 (RegEax, 20, 27);
*DisplayedFamily += ExtendedFamilyId;
}
}
//
// The Extended Model ID needs to be examined only when the Family ID is 06H or 0FH.
// If Family ID is 06H or 0FH, Displayed Model ID = Model ID + (Extended Model ID << 4).
// Otherwise, Displayed Model ID is Model ID.
//
if (DisplayedModel != NULL) {
*DisplayedModel = BitFieldRead32 (RegEax, 4, 7);
if (FamilyId == 0x06 || FamilyId == 0x0f) {
ExtendedModelId = BitFieldRead32 (RegEax, 16, 19);
*DisplayedModel += (ExtendedModelId << 4);
}
}
}
/**
Get initial local APIC ID of specified logical processor
This function gets initial local APIC ID of specified logical processor.
@param ProcessorNumber Handle number of specified logical processor
@return Initial local APIC ID of specified logical processor
**/
UINT32
EFIAPI
GetInitialLocalApicId (
UINTN ProcessorNumber
)
{
CPU_COLLECTED_DATA *CpuCollectedData;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
CpuCollectedData = &mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber];
return (CpuCollectedData->CpuidData.CpuIdLeaf[1].RegEbx >> 24) & 0xff;
}
/**
Get the location of specified processor.
This function gets the location of specified processor, including
package number, core number within package, thread number within core.
@param ProcessorNumber Handle number of specified logical processor.
@param PackageNumber Pointer to the output package number.
@param CoreNumber Pointer to the output core number.
@param ThreadNumber Pointer to the output thread number.
**/
VOID
EFIAPI
GetProcessorLocation (
IN UINTN ProcessorNumber,
OUT UINT32 *PackageNumber OPTIONAL,
OUT UINT32 *CoreNumber OPTIONAL,
OUT UINT32 *ThreadNumber OPTIONAL
)
{
CPU_COLLECTED_DATA *CpuCollectedData;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
CpuCollectedData = &mCpuConfigLibConfigConextBuffer->CollectedDataBuffer[ProcessorNumber];
//
// If PackageNumber is not NULL, set the package number of the specified processor to it.
//
if (PackageNumber != NULL) {
*PackageNumber = CpuCollectedData->ProcessorLocation.Package;
}
//
// If CoreNumber is not NULL, set the core number within package to it.
//
if (CoreNumber != NULL) {
*CoreNumber = CpuCollectedData->ProcessorLocation.Core;
}
//
// If ThreadNumber is not NULL, set the thread number within core to it.
//
if (ThreadNumber != NULL) {
*ThreadNumber = CpuCollectedData->ProcessorLocation.Thread;
}
}
/**
Get the Feature entry at specified position in a feature list.
This function gets the Feature entry at specified position in a feature list.
@param ProcessorNumber Handle number of specified logical processor
@param FeatureIndex The index of the node in feature list.
@param Attribute Pointer to output feature-specific attribute
@return Feature ID of specified feature. CpuFeatureMaximum means not found
**/
CPU_FEATURE_ID
EFIAPI
GetProcessorFeatureEntry (
IN UINTN ProcessorNumber,
IN UINTN FeatureIndex,
OUT VOID **Attribute OPTIONAL
)
{
CPU_FEATURE_ENTRY *FeatureEntry;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
if (Attribute != NULL) {
*Attribute = NULL;
}
//
// Search for specified entry. If not found, return CpuFeatureMaximum.
//
FeatureEntry = SearchFeatureEntry (ProcessorNumber, FeatureIndex);
if (FeatureEntry == NULL) {
return CpuFeatureMaximum;
}
//
// If Attribute is not NULL, set the feature-specified attribute to it.
//
if (Attribute != NULL) {
*Attribute = FeatureEntry->Attribute;
}
return (FeatureEntry->FeatureID);
}
/**
Append a feature entry at the end of a feature list.
This function appends a feature entry at the end of a feature list.
@param ProcessorNumber Handle number of specified logical processor
@param FeatureID ID of the specified feature.
@param Attribute Feature-specific attribute.
@retval EFI_SUCCESS This function always return EFI_SUCCESS
**/
EFI_STATUS
EFIAPI
AppendProcessorFeatureIntoList (
IN UINTN ProcessorNumber,
IN CPU_FEATURE_ID FeatureID,
IN VOID *Attribute
)
{
LIST_ENTRY *List;
CPU_FEATURE_ENTRY *NewEntry;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
List = &mCpuConfigLibConfigConextBuffer->FeatureLinkListEntry[ProcessorNumber];
//
// Create a new feature node with given Feature ID and feature-specific attribute
//
NewEntry = CreateFeatureEntry (FeatureID, Attribute);
//
// Append the new node at the end of the list
//
InsertTailList (List, &(NewEntry->Link));
return EFI_SUCCESS;
}
/**
Delete a feature entry in a feature list.
This function deletes a feature entry in a feature list.
@param ProcessorNumber Handle number of specified logical processor
@param FeatureIndex The index of the node in feature list.
@retval EFI_SUCCESS The feature node successfully removed.
@retval EFI_INVALID_PARAMETER FeatureIndex surpasses the length of list.
**/
EFI_STATUS
EFIAPI
DeleteProcessorFeatureFromList (
IN UINTN ProcessorNumber,
IN UINTN FeatureIndex
)
{
CPU_FEATURE_ENTRY *FeatureEntry;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
//
// Search for specified entry. If SearchFeatureEntry() returns NULL, then
// it means FeatureIndex surpasses the length of list.
// Return EFI_INVALID_PARAMETER.
//
FeatureEntry = SearchFeatureEntry (ProcessorNumber, FeatureIndex);
if (FeatureEntry == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Remove the entry from list, and free its memory region.
//
RemoveEntryList (&(FeatureEntry->Link));
FreePool (FeatureEntry);
return EFI_SUCCESS;
}
/**
Insert a feature entry into a feature list.
This function insert a feature entry into a feature list before a node specified by Feature Index.
@param ProcessorNumber Handle number of specified logical processor
@param FeatureIndex The index of the new node in feature list.
@param FeatureID ID of the specified feature.
@param Attribute Feature-specific attribute.
@retval EFI_SUCCESS The feature node successfully inserted.
@retval EFI_INVALID_PARAMETER FeatureIndex surpasses the length of list.
**/
EFI_STATUS
EFIAPI
InsertProcessorFeatureIntoList (
IN UINTN ProcessorNumber,
IN UINTN FeatureIndex,
IN CPU_FEATURE_ID FeatureID,
IN VOID *Attribute
)
{
CPU_FEATURE_ENTRY *FeatureEntry;
CPU_FEATURE_ENTRY *NewEntry;
//
// Search for specified entry. If SearchFeatureEntry() returns NULL, then
// it means FeatureIndex surpasses the length of list.
// Return EFI_INVALID_PARAMETER.
//
FeatureEntry = SearchFeatureEntry (ProcessorNumber, FeatureIndex);
if (FeatureEntry == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Create a new feature node with given Feature ID and feature-specific attribute
//
NewEntry = CreateFeatureEntry (FeatureID, Attribute);
//
// Insert the new node before specified feature entry.
//
InsertHeadList (&(FeatureEntry->Link), &(NewEntry->Link));
return EFI_SUCCESS;
}
/**
Add an entry in specified register table.
This function adds an entry in specified register table, with given register type,
register index, bit section and value.
@param PreSmmInit Specify the target register table.
If TRUE, the target is the pre-SMM-init register table.
If FALSE, the target is the post-SMM-init register table.
@param ProcessorNumber Handle number of specified logical processor
@param RegisterType Type of the register to program
@param Index Index of the register to program
@param ValidBitStart Start of the bit section
@param ValidBitLength Length of the bit section
@param Value Value to write
**/
VOID
EFIAPI
WriteRegisterTableEx (
IN BOOLEAN PreSmmInit,
IN UINTN ProcessorNumber,
IN REGISTER_TYPE RegisterType,
IN UINT32 Index,
IN UINT8 ValidBitStart,
IN UINT8 ValidBitLength,
IN UINT64 Value
)
{
EFI_STATUS Status;
CPU_REGISTER_TABLE *RegisterTable;
EFI_PHYSICAL_ADDRESS Address;
UINTN AllocatePages;
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
if (PreSmmInit) {
RegisterTable = &mCpuConfigLibConfigConextBuffer->PreSmmInitRegisterTable[ProcessorNumber];
} else {
RegisterTable = &mCpuConfigLibConfigConextBuffer->RegisterTable[ProcessorNumber];
}
//
// If register table is full, allocate one more page for it.
// It must be in ACPI NVS memory under 4G, for consumption by S3 resume.
//
if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {
Address = 0xffffffff;
AllocatePages = RegisterTable->AllocatedSize / EFI_PAGE_SIZE;
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiACPIMemoryNVS,
AllocatePages + 1,
&Address
);
ASSERT_EFI_ERROR (Status);
//
// If there are records existing in the register table, then copy its contents
// to new region and free the old one.
//
if (RegisterTable->AllocatedSize > 0) {
CopyMem (
(VOID *) (UINTN) Address,
RegisterTable->RegisterTableEntry,
RegisterTable->AllocatedSize
);
//
// RegisterTableEntry is allocated by gBS AllocatePages() service.
// So, gBS FreePages() servcie is used to free it.
//
gBS->FreePages (
(EFI_PHYSICAL_ADDRESS) (UINTN) (VOID *) RegisterTable->RegisterTableEntry,
AllocatePages
);
}
//
// Adjust the allocated size and register table base address.
//
RegisterTable->AllocatedSize += EFI_PAGE_SIZE;
RegisterTable->RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) Address;
}
//
// Append entry in the register table.
//
RegisterTable->RegisterTableEntry[RegisterTable->TableLength].RegisterType = RegisterType;
RegisterTable->RegisterTableEntry[RegisterTable->TableLength].Index = Index;
RegisterTable->RegisterTableEntry[RegisterTable->TableLength].ValidBitStart = ValidBitStart;
RegisterTable->RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength;
RegisterTable->RegisterTableEntry[RegisterTable->TableLength].Value = Value;
RegisterTable->TableLength++;
}
/**
Add an entry in the post-SMM-init register table.
This function adds an entry in the post-SMM-init register table, with given register type,
register index, bit section and value.
@param ProcessorNumber Handle number of specified logical processor
@param RegisterType Type of the register to program
@param Index Index of the register to program
@param ValidBitStart Start of the bit section
@param ValidBitLength Length of the bit section
@param Value Value to write
**/
VOID
EFIAPI
WriteRegisterTable (
IN UINTN ProcessorNumber,
IN REGISTER_TYPE RegisterType,
IN UINT32 Index,
IN UINT8 ValidBitStart,
IN UINT8 ValidBitLength,
IN UINT64 Value
)
{
WriteRegisterTableEx (
FALSE,
ProcessorNumber,
RegisterType,
Index,
ValidBitStart,
ValidBitLength,
Value
);
}
/**
Add an entry in the pre-SMM-init register table.
This function adds an entry in the pre-SMM-init register table, with given register type,
register index, bit section and value.
@param ProcessorNumber Handle number of specified logical processor
@param RegisterType Type of the register to program
@param Index Index of the register to program
@param ValidBitStart Start of the bit section
@param ValidBitLength Length of the bit section
@param Value Value to write
**/
VOID
EFIAPI
WritePreSmmInitRegisterTable (
IN UINTN ProcessorNumber,
IN REGISTER_TYPE RegisterType,
IN UINT32 Index,
IN UINT8 ValidBitStart,
IN UINT8 ValidBitLength,
IN UINT64 Value
)
{
WriteRegisterTableEx (
TRUE,
ProcessorNumber,
RegisterType,
Index,
ValidBitStart,
ValidBitLength,
Value
);
}
/**
Set the sequence of processor setting.
This function sets the a processor setting at the position in
setting sequence specified by Index.
@param Index The zero-based index in the sequence.
@param ProcessorNumber Handle number of the processor to set.
@retval EFI_SUCCESS The sequence successfully modified.
@retval EFI_INVALID_PARAMETER Index surpasses the boundary of sequence.
@retval EFI_NOT_FOUND Processor specified by ProcessorNumber does not exist.
**/
EFI_STATUS
SetSettingSequence (
IN UINTN Index,
IN UINTN ProcessorNumber
)
{
ASSERT (mCpuConfigLibConfigConextBuffer != NULL);
//
// Check whether parameter Index is valid.
//
if (Index >= mCpuConfigLibConfigConextBuffer->NumberOfProcessors) {
return EFI_INVALID_PARAMETER;
}
//
// Check whether parameter ProcessorNumber is valid.
//
if (ProcessorNumber >= mCpuConfigLibConfigConextBuffer->NumberOfProcessors) {
return EFI_NOT_FOUND;
}
mCpuConfigLibConfigConextBuffer->SettingSequence[Index] = ProcessorNumber;
return EFI_SUCCESS;
}
/**
Set PcdCpuCallbackSignal, and then read the value back.
This function sets PCD entry PcdCpuCallbackSignal. If there is callback
function registered on it, the callback function will be triggered, and
it may change the value of PcdCpuCallbackSignal. This function then reads
the value of PcdCpuCallbackSignal back, the check whether it has been changed.
@param Value The value to set to PcdCpuCallbackSignal.
@return The value of PcdCpuCallbackSignal read back.
**/
UINT8
SetAndReadCpuCallbackSignal (
IN UINT8 Value
)
{
//
// Set PcdCpuCallbackSignal, and trigger callback function
//
PcdSet8 (PcdCpuCallbackSignal, Value);
//
// Read the value of PcdCpuCallbackSignal back. It may have been
// changed by callback function.
//
return (PcdGet8 (PcdCpuCallbackSignal));
}
/**
Worker function to create a new feature entry.
This is a worker function to create a new feature entry. The new entry is added to
the feature list by other functions in the library.
@param FeatureID The ID of the feature.
@param Attribute Feature-specific data.
@return Pointer to the created entry.
**/
CPU_FEATURE_ENTRY *
CreateFeatureEntry (
IN CPU_FEATURE_ID FeatureID,
IN VOID *Attribute
)
{
CPU_FEATURE_ENTRY *Node;
Node = AllocateZeroPool (sizeof (CPU_FEATURE_ENTRY));
ASSERT (Node != NULL);
Node->Signature = EFI_CPU_FEATURE_ENTRY_SIGNATURE;
Node->FeatureID = FeatureID;
Node->Attribute = Attribute;
return Node;
}
/**
Worker function to search for a feature entry in processor feature list.
This is a worker function to search for a feature entry in processor feature list.
@param ProcessorNumber Handle number of specified logical processor
@param FeatureIndex The index of the node in feature list.
@return Pointer to the feature node. If FeatureIndex surpasses the length of list, NULL is returned.
**/
CPU_FEATURE_ENTRY *
SearchFeatureEntry (
IN UINTN ProcessorNumber,
IN UINTN FeatureIndex
)
{
LIST_ENTRY *List;
LIST_ENTRY *Link;
CPU_FEATURE_ENTRY *FeatureEntry;
UINTN Index;
List = &mCpuConfigLibConfigConextBuffer->FeatureLinkListEntry[ProcessorNumber];
//
// Get the first node in list. If list is empty, return NULL.
//
Link = GetFirstNode (List);
if (IsNull (List, Link)) {
return NULL;
}
//
// Try to get the node specified by Index. If not found, return NULL.
//
for (Index = 1; Index < FeatureIndex; Index++) {
Link = GetNextNode (List, Link);
if (IsNull (List, Link)) {
return NULL;
}
}
FeatureEntry = CPU_FEATURE_ENTRY_FROM_LINK (Link);
return FeatureEntry;
}