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

📄 page.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.


Module Name:

Abstract:




Revision History

--*/

#include "imem.h"

#define EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT  (EFI_PAGE_SIZE)

#ifdef EFI64
#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT  (EFI_PAGE_SIZE * 2)
#else
#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT  (EFI_PAGE_SIZE)
#endif

//
// MemoryMap - the curernt memory map
//

UINTN           MemoryMapKey = 0;

//
// MapStack - space to use as temp storage to build new map descriptors
// MapDepth - depth of new descriptor stack
//

#define MAX_MAP_DEPTH   6
UINTN           MapDepth = 0;
MEMORY_MAP      MapStack[MAX_MAP_DEPTH];
UINTN           FreeMapStack = 0;

//
// Watermarks to cooalese like memory types (IA-32 values)
//
#define EFI_RUNTIME_SERVICES_CODE_RESERVE (0x010000 * sizeof(UINTN))
#define EFI_RUNTIME_SERVICES_DATA_RESERVE (0x030000 * sizeof(UINTN))
#define EFI_BOOT_SERVICES_CODE_RESERVE    (0x080000 * sizeof(UINTN))
#define EFI_BOOT_SERVICES_DATA_RESERVE    (0x140000 * sizeof(UINTN))

UINT64 EfiWatermarkRuntimeServicesCode = MAX_ADDRESS;
UINT64 EfiWatermarkRuntimeServicesData = MAX_ADDRESS;
UINT64 EfiWatermarkBootServicesCode    = MAX_ADDRESS;
UINT64 EfiWatermarkBootServicesData    = MAX_ADDRESS;
UINT64 EfiWatermarkDefault             = MAX_ADDRESS;

//
// Internal prototypes
//

STATIC
VOID
AddRange (
    IN EFI_MEMORY_TYPE              Type,
    IN EFI_PHYSICAL_ADDRESS         Start,
    IN EFI_PHYSICAL_ADDRESS         End,
    IN UINT64                       Attribute
    );

    
STATIC
VOID
FreeMemoryMapStack (
    VOID
    );

STATIC
EFI_STATUS
ConvertPages (
    IN BOOLEAN              LoadConvert,
    IN UINT64               Start,
    IN UINT64               NoPages,
    IN EFI_MEMORY_TYPE      NewType
    );

STATIC
UINT64
FindFreePages (
    IN UINT64               MaxAddress,
    IN UINT64               NoPages,
    IN EFI_MEMORY_TYPE      NewType,
    IN UINTN                Alignment
    );

STATIC
VOID
RemoveMemoryMapEntry (
    MEMORY_MAP          *Entry
    );

//
//
//


VOID
InitializeMemoryMap (
    VOID
    )
/*++

Routine Description:

    Initialize memory subsystem

Arguments:

    None

Returns:

    None

--*/
{
    InitializeLock (&MemoryLock, TPL_NOTIFY);
    InitializeListHead (&MemoryMap);
    InitializePool ();
    MemoryMapKey = 0;
    MapDepth = 0;
    FreeMapStack = 0;
}

VOID
InitializeMemoryMapWatermarks (
  VOID
  )

{
  EFI_STATUS  BootServicesCodeStatus;
  EFI_STATUS  BootServicesDataStatus;
  EFI_STATUS  RuntimeServicesCodeStatus;
  EFI_STATUS  RuntimeServicesDataStatus;
  UINTN       Count;

  RuntimeServicesDataStatus = AllocatePages (
                                AllocateMaxAddress,
                                EfiRuntimeServicesData,
                                EFI_RUNTIME_SERVICES_DATA_RESERVE >> EFI_PAGE_SHIFT,
                                &EfiWatermarkRuntimeServicesData
                                );

  RuntimeServicesCodeStatus = AllocatePages (
                                AllocateMaxAddress,
                                EfiRuntimeServicesCode,
                                EFI_RUNTIME_SERVICES_CODE_RESERVE >> EFI_PAGE_SHIFT,
                                &EfiWatermarkRuntimeServicesCode
                                );

  BootServicesCodeStatus = AllocatePages (
                             AllocateMaxAddress,
                             EfiBootServicesCode,
                             EFI_BOOT_SERVICES_CODE_RESERVE >> EFI_PAGE_SHIFT,
                             &EfiWatermarkBootServicesCode
                             );

  BootServicesDataStatus = AllocatePages (
                             AllocateMaxAddress,
                             EfiBootServicesData,
                             EFI_BOOT_SERVICES_DATA_RESERVE >> EFI_PAGE_SHIFT,
                             &EfiWatermarkBootServicesData
                             );

  Count = 0;
  if (!EFI_ERROR (RuntimeServicesCodeStatus)) {
    FreePages (EfiWatermarkRuntimeServicesCode, EFI_RUNTIME_SERVICES_CODE_RESERVE >> EFI_PAGE_SHIFT);
    EfiWatermarkRuntimeServicesCode += (EFI_RUNTIME_SERVICES_CODE_RESERVE - 1);
    Count++;
  }
  if (!EFI_ERROR (RuntimeServicesDataStatus)) {
    FreePages (EfiWatermarkRuntimeServicesData, EFI_RUNTIME_SERVICES_DATA_RESERVE >> EFI_PAGE_SHIFT);
    EfiWatermarkRuntimeServicesData += (EFI_RUNTIME_SERVICES_DATA_RESERVE - 1);
    Count++;
  }
  if (!EFI_ERROR (BootServicesCodeStatus)) {
    FreePages (EfiWatermarkBootServicesCode, EFI_BOOT_SERVICES_CODE_RESERVE >> EFI_PAGE_SHIFT);
    EfiWatermarkBootServicesCode += (EFI_BOOT_SERVICES_CODE_RESERVE - 1);
    Count++;
  }
  if (!EFI_ERROR (BootServicesDataStatus)) {
    FreePages (EfiWatermarkBootServicesData, EFI_BOOT_SERVICES_DATA_RESERVE >> EFI_PAGE_SHIFT);
    EfiWatermarkDefault = EfiWatermarkBootServicesData - 1;
    EfiWatermarkBootServicesData += (EFI_BOOT_SERVICES_DATA_RESERVE - 1);
    Count++;
  }

  if (Count != 4) {
    EfiWatermarkRuntimeServicesCode = MAX_ADDRESS;
    EfiWatermarkRuntimeServicesData = MAX_ADDRESS;
    EfiWatermarkBootServicesCode = MAX_ADDRESS;
    EfiWatermarkBootServicesData = MAX_ADDRESS;
    EfiWatermarkDefault = MAX_ADDRESS;
  }
}
    
VOID
FwAddMemoryDescriptor (
    IN EFI_MEMORY_TYPE          Type,
    IN EFI_PHYSICAL_ADDRESS     Start,
    IN UINT64                   NoPages,
    IN UINT64                   Attribute
    )
/*++

Routine Description:

    Called to initialize the memory map and add descriptors to
    the current descriptor list.

    N.B. The first descriptor that is added must be general usable
    memory as the addition allocates heap.

Arguments:

    Type        - The type of memory to add

    Start       - The starting address in the memory range.
                  Must be page aligned.

    NoPages     - The number of pages in the range

    Attribute   - Attributes of the memory to add

Returns:

    None.  The range is added to the memroy map.

--*/
{
    EFI_PHYSICAL_ADDRESS            End;

    AcquireLock (&MemoryLock);
    End = Start + LShiftU64(NoPages, EFI_PAGE_SHIFT) - 1;
    AddRange (Type, Start, End, Attribute);
    FreeMemoryMapStack ();
    ReleaseLock (&MemoryLock);
}


STATIC
VOID
AddRange (
    IN EFI_MEMORY_TYPE              Type,
    IN EFI_PHYSICAL_ADDRESS         Start,
    IN EFI_PHYSICAL_ADDRESS         End,
    IN UINT64                       Attribute
    )
/*++

Routine Description:

    Internal function.  Adds a ranges to the memory map.  The
    range must not already exist in the map.

Arguments:

    Type        - The type of memory range to add

    Start       - The starting address in the memory range
                  Must be paged aligned.

    End         - The last address in the range
                  Must be the last byte of a page.

    Attribute   - The attributes of the memory range to add

Returns:

    None.  The range is added to the memroy map.

--*/
{
    LIST_ENTRY          *Link;
    MEMORY_MAP          *Entry;
    MEMORY_MAP          *Entry1;
    BOOLEAN             Merge;

    ASSERT ((Start & EFI_PAGE_MASK) == 0);
    ASSERT (End > Start) ;

    ASSERT_LOCKED (&MemoryLock);
    DEBUG((D_PAGE, "AddRange: %lx-%lx to %d\n", Start, End, Type));

    //
    // Memory map being altered
    //

    MemoryMapKey += 1;
    
    //
    // Look for adjoining memory descriptor
    //
    // Two memory descriptors can only be merged if they have the same Type
    // and the same Attribute.
    //

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

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

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

        if (Entry->End + 1 == Start) {
            Entry->End = End;
            Merge = TRUE;

        } 
        else if (Entry->Start == End + 1) {
            Entry->Start = Start;
            Merge = TRUE;
        }

        if (Merge) {
            Link = MemoryMap.Flink;
            while (Link != &MemoryMap) {
                Entry1 = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
                Link  = Link->Flink;

                if (Entry->Type != Entry1->Type) {
                  continue;
                }
                if (Entry->Attribute != Entry1->Attribute) {
                  continue;
                }
                if (Entry->End + 1 == Entry1->Start) {
                  Entry1->Start = Entry->Start;
                  RemoveMemoryMapEntry (Entry);
                  return;
                } else if (Entry->Start == Entry1->End + 1) {
                  Entry1->End = Entry->End;
                  RemoveMemoryMapEntry (Entry);
                  return;
                }
            }
            return;
        }
    }

    //
    // Add descriptor 
    //

    MapStack[MapDepth].Signature = MEMORY_MAP_SIGNATURE;
    MapStack[MapDepth].FromPool = FALSE;
    MapStack[MapDepth].Type = Type;
    MapStack[MapDepth].Start = Start;
    MapStack[MapDepth].End = End;
    MapStack[MapDepth].VirtualStart = 0;
    MapStack[MapDepth].Attribute = Attribute;
    InsertTailList (&MemoryMap, &MapStack[MapDepth].Link);

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


STATIC
VOID
FreeMemoryMapStack (
    VOID
    )
/*++

Routine Description:

    Internal function.  Moves any memory descriptors that are on the
    temporary descriptor stack to heap.

Arguments:

    None.

Returns:

    None.

--*/
{
    MEMORY_MAP      *Entry, *Entry2;
    LIST_ENTRY      *Link2;

    ASSERT_LOCKED (&MemoryLock);

    //
    // If already freeing the map stack, then return
    //

    if (FreeMapStack) {
        return ;
    }

    //
    // Move the temporary memory descriptor stack into pool
    //

    FreeMapStack += 1;

    while (MapDepth) {

        //
        // Allocate memory for a entry
        //

        Entry = AllocatePoolI (EfiRuntimeServicesData, sizeof(MEMORY_MAP));

        //
        // Update to proper entry
        //

        MapDepth -= 1;

        if (MapStack[MapDepth].Link.Flink) {
            //
            // Move this entry to general pool
            //

            RemoveEntryList (&MapStack[MapDepth].Link);
            MapStack[MapDepth].Link.Flink = NULL;

            *Entry = MapStack[MapDepth];
            Entry->FromPool = TRUE;

            //
            // Find insertion location
            //

            for (Link2 = MemoryMap.Flink; Link2 != &MemoryMap; Link2 = Link2->Flink) {
                Entry2 = CR(Link2, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
                if (Entry2->FromPool && Entry2->Start > Entry->Start) {
                    break;
                }
            }

            InsertTailList (Link2, &Entry->Link);

        } else {

            //
            // It was removed, don't move it
            //

            FreePoolI (Entry);

        }
    }


    FreeMapStack -= 1;
}

STATIC
VOID
RemoveMemoryMapEntry (
    MEMORY_MAP          *Entry
    )
/*++

Routine Description:

⌨️ 快捷键说明

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