⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 page.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 3 页
字号:
    Internal function.  Removes a descrptor entry.

Arguments:

    Entry       - The entry to remove

Returns:

    None.

--*/
{
    RemoveEntryList (&Entry->Link);
    Entry->Link.Flink = NULL;

    if (Entry->FromPool) {
        FreePoolI (Entry);
    }
}


STATIC
EFI_STATUS
ConvertPages (
    IN BOOLEAN              LoadConvert,
    IN UINT64               Start,
    IN UINT64               NoPages,
    IN EFI_MEMORY_TYPE      NewType
    )
/*++

Routine Description:

    Internal function.  Converts a memory range to the specified type.
    The range must exist in the memory map.

Arguments:

    LoadConvert     - Signifies that the range is being converted on behalf
                      of the loader

    Start           - The first address of the range.
                      Must be page aligned.

    NoPages         - The number of pages to convert

    NewType         - The new type for the memory range

Returns:

    Status.

--*/
{

    UINT64                  NoBytes, End, RangeEnd, Attribute;
    LIST_ENTRY              *Link;
    MEMORY_MAP              *Entry;

    NoBytes = LShiftU64(NoPages, EFI_PAGE_SHIFT);
    End = Start + NoBytes - 1;

    ASSERT (!EfiAtRuntime);
    ASSERT (NoPages);
    ASSERT ((Start & EFI_PAGE_MASK) == 0);
    ASSERT (End > Start) ;
    ASSERT_LOCKED (&MemoryLock);

    if (!NoPages || (Start & EFI_PAGE_MASK) || (Start > Start + NoBytes)) {
        return EFI_INVALID_PARAMETER;
    }

    //
    // Convert the entire range
    //

    while (Start < End) {

        //
        // Find the entry that the covers the range
        //

        for (Link = MemoryMap.Flink; Link != &MemoryMap; Link = Link->Flink) {
            Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);

            if (Entry->Start <= Start && Entry->End > Start) {
                break;
            }
        }

        if (Link == &MemoryMap) {
            DEBUG((D_ERROR, "ConvertPages: failed to find range %lx - %lx\n", Start, End));
            return EFI_NOT_FOUND;
        }

        //
        // Convert range to the end, or to the end of the descriptor
        // if that's all we've got
        //

        RangeEnd = End;
        if (Entry->End < End) {
            RangeEnd = Entry->End;
        }

        DEBUG((D_PAGE, "ConvertRange: %lx-%lx to %d\n", Start, RangeEnd, NewType));

        //
        // Debug code - verify conversion is allowed
        //

        if (!LoadConvert && 
            !(NewType == EfiConventionalMemory ? 1 : 0) ^ (Entry->Type == EfiConventionalMemory ? 1 : 0)) {
            DEBUG((D_ERROR, "ConvertPages: Incompatible memory types\n"));
            return EFI_NOT_FOUND;
        }    

        //
        // Memory map being altered
        //

        MemoryMapKey += 1;

        //
        // Pull range out of descritpr
        //

        if (Entry->Start == Start) {

            // clip start
            Entry->Start = RangeEnd + 1;

        } else if (Entry->End == RangeEnd) {

            // clip end
            Entry->End = Start - 1;

        } else {

            // pull it out of the center. clip current

            // add a new one
            MapStack[MapDepth].Signature = MEMORY_MAP_SIGNATURE;
            MapStack[MapDepth].FromPool = FALSE;
            MapStack[MapDepth].Type = Entry->Type;
            MapStack[MapDepth].Start = RangeEnd+1;
            MapStack[MapDepth].End = Entry->End;

            //
            // Inherit Attribute from the Memory Descriptor that is being clipped
            //

            MapStack[MapDepth].Attribute = Entry->Attribute;

            Entry->End = Start - 1;
            ASSERT (Entry->Start < Entry->End);

            Entry = &MapStack[MapDepth];
            InsertTailList (&MemoryMap, &Entry->Link);

            MapDepth += 1;
            ASSERT (MapDepth < MAX_MAP_DEPTH);
        }

        //
        // The new range inherits the same Attribute as the Entry it is being cut out of.
        //

        Attribute = Entry->Attribute;

        //
        // If the descriptor is empty, then remove it from the map
        //

        if (Entry->Start == Entry->End + 1) {
            RemoveMemoryMapEntry (Entry);
            Entry = NULL;
        }
        
        //
        // Add our new range in
        //

        AddRange (NewType, Start, RangeEnd, Attribute);

        //
        // Move any map descriptor stack to general pool
        //

        FreeMemoryMapStack ();

        //
        // Bump the starting address, and convert the next range
        //

        Start = RangeEnd + 1;
    }

    //
    // Coverted the whole range, done
    //

    return EFI_SUCCESS;
}

STATIC
UINT64
FindFreePagesI (
    IN UINT64           MaxAddress,
    IN UINT64           NoPages,
    IN EFI_MEMORY_TYPE  NewType,
    IN UINTN            Alignment
    )
/*++

Routine Description:

    Internal function.  Finds a consecutive free page range below
    the requested address

Arguments:

    MaxAddress          - The address that the range must be below

    NoPages             - Number of pages needed

    NewType             - The type of memory the range is going to be turned into

Returns:

    The base address of the range, or 0 if the range was not found.

--*/
{
    UINT64              NoBytes, Target;
    UINT64              DescStart, DescEnd, DescNoBytes;
    LIST_ENTRY          *Link;
    MEMORY_MAP          *Entry;

    if (MaxAddress < EFI_PAGE_MASK) {
    	return 0;
    }
    
    if ((MaxAddress & EFI_PAGE_MASK) != EFI_PAGE_MASK) {
    									// if MaxAddress is not aligned to the end of a page
       	MaxAddress -= (EFI_PAGE_MASK + 1);	// Change MaxAddress to be 1 page lower
        MaxAddress &= ~EFI_PAGE_MASK;		// set MaxAddress to a page boundary
        MaxAddress |= EFI_PAGE_MASK;		// set MaxAddress to end of the page
    }

    if (!NoPages) {
        return 0;
    }

    NoBytes = LShiftU64(NoPages, EFI_PAGE_SHIFT);
    Target = 0;

    for (Link = MemoryMap.Flink; Link != &MemoryMap; Link = Link->Flink) {
        Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
    
        //
        // If it's not a free entry, don't bother with it
        //

        if (Entry->Type != EfiConventionalMemory) {
            continue;
        }

        DescStart = Entry->Start;
        DescEnd = Entry->End;

        //
        // If desc is past max allowed address, skip it
        //

        if (DescStart >= MaxAddress) {
            continue;
        }

        //
        // If desc ends past max allowed address, clip the end
        //

        if (DescEnd >= MaxAddress) {
            DescEnd = MaxAddress;
        }

        DescEnd = ((DescEnd + 1) & (~(Alignment - 1))) - 1;

        //
        // Compute the number of bytes we can used from this 
        // descriptor, and see it's enough to statisfy the request
        //

//        DescNoBytes = Entry->End - Entry->Start + 1;
        DescNoBytes = DescEnd - DescStart + 1;

        if (DescNoBytes >= NoBytes) {

            //
            // If this is the best match so far remember it
            //

        
            if (DescEnd > Target) {
                Target = DescEnd;
            }
        }
    }                    

    //
    // If this is a grow down, adjust target to be the allocation base
    //

    Target -= NoBytes - 1;

    //
    // If we didn't find a match, return 0
    //

    if (Target & EFI_PAGE_MASK) {
        Target = 0;
    }

    return Target;
}

STATIC
UINT64
FindFreePages (
    IN UINT64           MaxAddress,
    IN UINT64           NoPages,
    IN EFI_MEMORY_TYPE  NewType,
    IN UINTN            Alignment
    )
/*++

Routine Description:

    Internal function.  Finds a consecutive free page range below
    the requested address

Arguments:

    MaxAddress          - The address that the range must be below

    NoPages             - Number of pages needed

    NewType             - The type of memory the range is going to be turned into

Returns:

    The base address of the range, or 0 if the range was not found.

--*/
{
    UINT64  NewMaxAddress;
    UINT64  Start;

    NewMaxAddress = MaxAddress;

    switch (NewType) {
    case EfiRuntimeServicesCode:
      if (MaxAddress > EfiWatermarkRuntimeServicesCode) {
        NewMaxAddress = EfiWatermarkRuntimeServicesCode;
      }
      break;
    case EfiRuntimeServicesData:
      if (MaxAddress > EfiWatermarkRuntimeServicesData) {
        NewMaxAddress = EfiWatermarkRuntimeServicesData;
      }
      break;
    case EfiBootServicesCode:
      if (MaxAddress > EfiWatermarkBootServicesCode) {
        NewMaxAddress = EfiWatermarkBootServicesCode;
      }
      break;
    case EfiBootServicesData:
      if (MaxAddress > EfiWatermarkBootServicesData) {
        NewMaxAddress = EfiWatermarkBootServicesData;
      }
      break;
    case EfiLoaderCode:
    case EfiLoaderData:
    case EfiACPIReclaimMemory:
    case EfiACPIMemoryNVS:
    case EfiReservedMemoryType:
      if (MaxAddress > EfiWatermarkDefault) {
        NewMaxAddress = EfiWatermarkDefault;
      }
      break;
    }

    Start = FindFreePagesI (NewMaxAddress, NoPages, NewType, Alignment);
    if (!Start) {
      Start = FindFreePagesI (MaxAddress, NoPages, NewType, Alignment);
    }

    return Start;
}

EFI_STATUS
BOOTSERVICE
BootServiceAllocatePages (
    IN EFI_ALLOCATE_TYPE        Type,
    IN EFI_MEMORY_TYPE          MemoryType,
    IN UINTN                    NoPages,
    OUT EFI_PHYSICAL_ADDRESS    *Memory
    )
/*++

Routine Description:

    Allocates pages from the memory map.

Arguments:

    Type            - The type of allocation to perform

    MemoryType      - The type of memory to turn the allocated pages into.

    NoPages         - The number of pages to allocate

    Memory          - A pointer to recieve the base allocated memory address

Returns:

    Status.  On success, Memory is filled in with the base address allocated

--*/
{
    if (MemoryType >= EfiMaxMemoryType && MemoryType <= 0x7fffffff) {
        return EFI_INVALID_PARAMETER;
    }

    return AllocatePages(Type,MemoryType,NoPages,Memory);
}

EFI_STATUS
AllocatePages (
    IN EFI_ALLOCATE_TYPE        Type,
    IN EFI_MEMORY_TYPE          MemoryType,
    IN UINTN                    NoPages,
    OUT EFI_PHYSICAL_ADDRESS    *Memory
    )
/*++

Routine Description:

    Allocates pages from the memory map.

Arguments:

    Type            - The type of allocation to perform

    MemoryType      - The type of memory to turn the allocated pages into.

    NoPages         - The number of pages to allocate

    Memory          - A pointer to recieve the base allocated memory address

Returns:

    Status.  On success, Memory is filled in with the base address allocated

--*/
{
    EFI_STATUS              Status;
    UINT64                  Start, MaxAddress;
    UINTN                   Alignment;

    if (Type < AllocateAnyPages || Type >= MaxAllocateType) {
        return EFI_INVALID_PARAMETER;
    }

    if (EfiAtRuntime) {
        return EFI_UNSUPPORTED;
    }

    Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;

    if  (MemoryType == EfiACPIReclaimMemory   ||
         MemoryType == EfiACPIMemoryNVS       ||
         MemoryType == EfiRuntimeServicesCode ||
         MemoryType == EfiRuntimeServicesData    ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -