gcd.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,443 行 · 第 1/5 页
C
2,443 行
/*++
Copyright (c) 2004 - 2006, 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.
Module Name:
gcd.c
Abstract:
The file contains the GCD related services in the EFI Boot Services Table.
The GCD services are used to manage the memory and I/O regions that
are accessible to the CPU that is executing the DXE core.
--*/
#include "gcd.h"
#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000
#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
EFI_RESOURCE_ATTRIBUTE_TESTED | \
EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \
EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \
EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
EFI_RESOURCE_ATTRIBUTE_64_BIT_IO )
#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
EFI_RESOURCE_ATTRIBUTE_TESTED )
#define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
EFI_RESOURCE_ATTRIBUTE_INITIALIZED )
#define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
#define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff
//
// Module Variables
//
EFI_LOCK mGcdMemorySpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY);
EFI_LOCK mGcdIoSpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY);
EFI_LIST_ENTRY mGcdMemorySpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap);
EFI_LIST_ENTRY mGcdIoSpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap);
EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate = {
EFI_GCD_MAP_SIGNATURE,
{ NULL, NULL },
0,
0,
0,
0,
EfiGcdMemoryTypeNonExistent,
0,
NULL,
NULL
};
EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate = {
EFI_GCD_MAP_SIGNATURE,
{ NULL, NULL },
0,
0,
0,
0,
0,
EfiGcdIoTypeNonExistent,
NULL,
NULL
};
GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = {
{ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE, EFI_MEMORY_UC, TRUE },
{ EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED, EFI_MEMORY_UCE, TRUE },
{ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE, EFI_MEMORY_WC, TRUE },
{ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE, EFI_MEMORY_WT, TRUE },
{ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE, EFI_MEMORY_WB, TRUE },
{ EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED, EFI_MEMORY_RP, TRUE },
{ EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED, EFI_MEMORY_WP, TRUE },
{ EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED, EFI_MEMORY_XP, TRUE },
{ EFI_RESOURCE_ATTRIBUTE_PRESENT, EFI_MEMORY_PRESENT, FALSE },
{ EFI_RESOURCE_ATTRIBUTE_INITIALIZED, EFI_MEMORY_INITIALIZED, FALSE },
{ EFI_RESOURCE_ATTRIBUTE_TESTED, EFI_MEMORY_TESTED, FALSE },
{ 0, 0, FALSE }
};
VOID
CoreAcquireGcdMemoryLock (
VOID
)
/*++
Routine Description:
Acquire memory lock on mGcdMemorySpaceLock
Arguments:
None
Returns:
None
--*/
{
CoreAcquireLock (&mGcdMemorySpaceLock);
}
VOID
CoreReleaseGcdMemoryLock (
VOID
)
/*++
Routine Description:
Release memory lock on mGcdMemorySpaceLock
Arguments:
None
Returns:
None
--*/
{
CoreReleaseLock (&mGcdMemorySpaceLock);
}
VOID
CoreAcquireGcdIoLock (
VOID
)
/*++
Routine Description:
Acquire memory lock on mGcdIoSpaceLock
Arguments:
None
Returns:
None
--*/
{
CoreAcquireLock (&mGcdIoSpaceLock);
}
VOID
CoreReleaseGcdIoLock (
VOID
)
/*++
Routine Description:
Release memory lock on mGcdIoSpaceLock
Arguments:
None
Returns:
None
--*/
{
CoreReleaseLock (&mGcdIoSpaceLock);
}
//
// GCD Initialization Worker Functions
//
UINT64
AlignValue (
IN UINT64 Value,
IN UINTN Alignment,
IN BOOLEAN RoundUp
)
/*++
Routine Description:
Aligns a value to the specified boundary.
Arguments:
Value - 64 bit value to align
Alignment - Log base 2 of the boundary to align Value to
RoundUp - TRUE if Value is to be rounded up to the nearest aligned boundary.
FALSE is Value is to be rounded down to the nearest aligned boundary.
Returns:
A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
--*/
{
UINT64 AlignmentMask;
AlignmentMask = LShiftU64 (1, Alignment) - 1;
if (RoundUp) {
Value += AlignmentMask;
}
return Value & (~AlignmentMask);
}
UINT64
PageAlignAddress (
IN UINT64 Value
)
/*++
Routine Description:
Aligns address to the page boundary.
Arguments:
Value - 64 bit address to align
Returns:
A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
--*/
{
return AlignValue (Value, EFI_PAGE_SHIFT, TRUE);
}
UINT64
PageAlignLength (
IN UINT64 Value
)
/*++
Routine Description:
Aligns length to the page boundary.
Arguments:
Value - 64 bit length to align
Returns:
A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment.
--*/
{
return AlignValue (Value, EFI_PAGE_SHIFT, FALSE);
}
//
// GCD Memory Space Worker Functions
//
EFI_STATUS
CoreAllocateGcdMapEntry (
IN OUT EFI_GCD_MAP_ENTRY **TopEntry,
IN OUT EFI_GCD_MAP_ENTRY **BottomEntry
)
/*++
Routine Description:
Allocate pool for two entries.
Arguments:
TopEntry - An entry of GCD map
BottomEntry - An entry of GCD map
Returns:
EFI_OUT_OF_RESOURCES - No enough buffer to be allocated.
EFI_SUCCESS - Both entries successfully allocated.
--*/
{
*TopEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY));
if (*TopEntry == NULL) {
return EFI_OUT_OF_RESOURCES;
}
*BottomEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY));
if (*BottomEntry == NULL) {
CoreFreePool (*TopEntry);
return EFI_OUT_OF_RESOURCES;
}
return EFI_SUCCESS;
}
EFI_STATUS
CoreInsertGcdMapEntry (
IN EFI_LIST_ENTRY *Link,
IN EFI_GCD_MAP_ENTRY *Entry,
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN EFI_GCD_MAP_ENTRY *TopEntry,
IN EFI_GCD_MAP_ENTRY *BottomEntry
)
/*++
Routine Description:
Internal function. Inserts a new descriptor into a sorted list
Arguments:
Link - The linked list to insert the range BaseAddress and Length into
Entry - A pointer to the entry that is inserted
BaseAddress - The base address of the new range
Length - The length of the new range in bytes
TopEntry - Top pad entry to insert if needed.
BottomEntry - Bottom pad entry to insert if needed.
Returns:
EFI_SUCCESS - The new range was inserted into the linked list
--*/
{
ASSERT (Length != 0);
ASSERT (TopEntry->Signature == 0);
ASSERT (BottomEntry->Signature == 0);
if (BaseAddress > Entry->BaseAddress) {
EfiCommonLibCopyMem (BottomEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));
Entry->BaseAddress = BaseAddress;
BottomEntry->EndAddress = BaseAddress - 1;
InsertTailList (Link, &BottomEntry->Link);
}
if ((BaseAddress + Length - 1) < Entry->EndAddress) {
EfiCommonLibCopyMem (TopEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY));
TopEntry->BaseAddress = BaseAddress + Length;
Entry->EndAddress = BaseAddress + Length - 1;
InsertHeadList (Link, &TopEntry->Link);
}
return EFI_SUCCESS;
}
EFI_STATUS
CoreMergeGcdMapEntry (
IN EFI_LIST_ENTRY *Link,
IN BOOLEAN Forward,
IN EFI_LIST_ENTRY *Map
)
/*++
Routine Description:
Merge the Gcd region specified by Link and its adjacent entry
Arguments:
Link - Specify the entry to be merged (with its adjacent entry).
Forward - Direction (forward or backward).
Map - Boundary.
Returns:
EFI_SUCCESS - Successfully returned.
EFI_UNSUPPORTED - These adjacent regions could not merge.
--*/
{
EFI_LIST_ENTRY *AdjacentLink;
EFI_GCD_MAP_ENTRY *Entry;
EFI_GCD_MAP_ENTRY *AdjacentEntry;
//
// Get adjacent entry
//
if (Forward) {
AdjacentLink = Link->ForwardLink;
} else {
AdjacentLink = Link->BackLink;
}
//
// If AdjacentLink is the head of the list, then no merge can be performed
//
if (AdjacentLink == Map) {
return EFI_SUCCESS;
}
Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
AdjacentEntry = CR (AdjacentLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE);
if (Entry->Capabilities != AdjacentEntry->Capabilities) {
return EFI_UNSUPPORTED;
}
if (Entry->Attributes != AdjacentEntry->Attributes) {
return EFI_UNSUPPORTED;
}
if (Entry->GcdMemoryType != AdjacentEntry->GcdMemoryType) {
return EFI_UNSUPPORTED;
}
if (Entry->GcdIoType != AdjacentEntry->GcdIoType) {
return EFI_UNSUPPORTED;
}
if (Entry->ImageHandle != AdjacentEntry->ImageHandle) {
return EFI_UNSUPPORTED;
}
if (Entry->DeviceHandle != AdjacentEntry->DeviceHandle) {
return EFI_UNSUPPORTED;
}
if (Forward) {
Entry->EndAddress = AdjacentEntry->EndAddress;
} else {
Entry->BaseAddress = AdjacentEntry->BaseAddress;
}
RemoveEntryList (AdjacentLink);
CoreFreePool (AdjacentEntry);
return EFI_SUCCESS;
}
EFI_STATUS
CoreCleanupGcdMapEntry (
IN EFI_GCD_MAP_ENTRY *TopEntry,
IN EFI_GCD_MAP_ENTRY *BottomEntry,
IN EFI_LIST_ENTRY *StartLink,
IN EFI_LIST_ENTRY *EndLink,
IN EFI_LIST_ENTRY *Map
)
/*++
Routine Description:
Merge adjacent entries on total chain.
Arguments:
TopEntry - Top entry of GCD map.
BottomEntry - Bottom entry of GCD map.
StartLink - Start link of the list for this loop.
EndLink - End link of the list for this loop.
Map - Boundary.
Returns:
EFI_SUCCESS - GCD map successfully cleaned up.
--*/
{
EFI_LIST_ENTRY *Link;
if (TopEntry->Signature == 0) {
CoreFreePool (TopEntry);
}
if (BottomEntry->Signature == 0) {
CoreFreePool (BottomEntry);
}
Link = StartLink;
while (Link != EndLink->ForwardLink) {
CoreMergeGcdMapEntry (Link, FALSE, Map);
Link = Link->ForwardLink;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?