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

📄 page.c

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

      Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;
    }

    if (Type == AllocateAddress) {
      if ((*Memory & (Alignment - 1)) != 0) {
        return EFI_INVALID_PARAMETER;
      }
    }

    NoPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
    NoPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);

    //
    // If this is for below a particular address, then 
    //

    Start = *Memory;
    MaxAddress = MAX_ADDRESS;
    if (Type == AllocateMaxAddress) {
        MaxAddress = Start;
    }

    AcquireLock (&MemoryLock);
    
    //
    // If not a specific address, then find an address to allocate
    //

    if (Type != AllocateAddress) {
        Start = FindFreePages(MaxAddress, NoPages, MemoryType, Alignment);
        if (!Start) {
            Status = EFI_OUT_OF_RESOURCES;
            goto Done;
        }
    }

    //
    // Convert pages from FreeMemory to the requested type
    //

    Status = ConvertPages (FALSE, Start, NoPages, MemoryType);

Done:
    ReleaseLock (&MemoryLock);

    if (!EFI_ERROR(Status)) {
        *Memory = Start;
    }

    return Status;
}


EFI_STATUS 
BOOTSERVICE
FreePages (
    IN EFI_PHYSICAL_ADDRESS     Memory,
    IN UINTN                    NoPages
    )
/*++

Routine Description:

    Frees previous allocated pages.

Arguments:

    Memory          - Base address of memory being freed

    NoPages         - The number of pages to free

Returns:

    Status.

--*/
{
    EFI_STATUS          Status;
    LIST_ENTRY          *Link;
    MEMORY_MAP          *Entry;
    UINTN               Alignment;

    if (EfiAtRuntime) {
        return EFI_UNSUPPORTED;
    }

    //
    // Free the range
    //
    AcquireLock (&MemoryLock);

    //
    // 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 <= Memory && Entry->End > Memory) {
            break;
        }
    }
    if (Link == &MemoryMap) {
      ReleaseLock (&MemoryLock);
      return EFI_NOT_FOUND;
    }

    Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;

    if  (Entry->Type == EfiACPIReclaimMemory   ||
         Entry->Type == EfiACPIMemoryNVS       ||
         Entry->Type == EfiRuntimeServicesCode ||
         Entry->Type == EfiRuntimeServicesData    ) {

      Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;

    }

    if ((Memory & (Alignment - 1)) != 0) {
      ReleaseLock (&MemoryLock);
      return EFI_INVALID_PARAMETER;
    }

    NoPages += EFI_SIZE_TO_PAGES (Alignment) - 1;
    NoPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);


    //
    //check if the NoPages is valid
    //
    if(!NoPages || NoPages > RShiftU64(Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT)){
        ReleaseLock(&MemoryLock);
        return EFI_INVALID_PARAMETER;
    }

    Status = ConvertPages (FALSE, Memory, NoPages, EfiConventionalMemory);
    ReleaseLock (&MemoryLock);

    if (EFI_ERROR(Status)) {
        return Status;
    }

    //
    // Destroy the contents
    //

    if (Memory < MAX_ADDRESS) {
        DBGSETMEM ((VOID *) Memory, NoPages << EFI_PAGE_SHIFT);
    }
    
    return Status;
}


EFI_STATUS
BOOTSERVICE
GetMemoryMap (
    IN OUT UINTN                    *MemoryMapSize,
    IN OUT EFI_MEMORY_DESCRIPTOR    *Desc,
    OUT UINTN                       *MapKey,
    OUT UINTN                       *DescriptorSize,
    OUT UINT32                      *DescriptorVersion
    )
/*++

Routine Description:

    Returns the current memory map.

Arguments:

    MemoryMapSize   - On input the sizeof of Desc
                      On output the amount of data return in Desc

    Desc            - The buffer to return the memory map in

    MapKey          - The address to return the current mapkey in

Returns:

    Status.
    On success, Desc & MemoryMapSize is completed with the current memory map.
    On buffer too small, MemoryMapSize is completed with the buffer size needed.

--*/
{
    UINTN                       BufferSize;
    EFI_STATUS                  Status;
    LIST_ENTRY                  *Link;
    MEMORY_MAP                  *Entry;
    UINTN                       Size;

    if (MemoryMapSize == NULL) {
      return EFI_INVALID_PARAMETER;
    }

    Size = sizeof(EFI_MEMORY_DESCRIPTOR);

    //
    // Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
    //  prevent people from having pointer math bugs in thier code.
    //  now you have to use *DescriptorSize to make things work.
    //
    Size += sizeof(UINT64) - (Size % sizeof(UINT64));

    if (DescriptorSize != NULL) {
      *DescriptorSize = Size;
    }

    if (DescriptorVersion != NULL) {
      *DescriptorVersion = EFI_MEMORY_DESCRIPTOR_VERSION;
    }

    AcquireLock (&MemoryLock);

    //
    // Compute the buffer size needed to fit the entire map
    //

    BufferSize = 0;
    for (Link = MemoryMap.Flink; Link != &MemoryMap; Link = Link->Flink) {
        BufferSize += Size;
    }

    if (*MemoryMapSize < BufferSize) {
        Status = EFI_BUFFER_TOO_SMALL;
        goto Done;
    }

    if (Desc == NULL) {
      Status = EFI_INVALID_PARAMETER;
      goto Done;
    }


    //
    // Build the map
    //

    ZeroMem (Desc, Size);
    for (Link = MemoryMap.Flink; Link != &MemoryMap; Link = Link->Flink) {
        Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
        ASSERT (!Entry->VirtualStart);

        Desc->Type = Entry->Type;
        Desc->PhysicalStart = Entry->Start;
        Desc->VirtualStart = Entry->VirtualStart;
        Desc->NumberOfPages = RShiftU64(Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT);
    
        switch (Entry->Type) {
            case EfiReservedMemoryType:
            case EfiUnusableMemory:
            case EfiACPIReclaimMemory:
            case EfiACPIMemoryNVS:
            case EfiMemoryMappedIO:
            case EfiMemoryMappedIOPortSpace:
            case EfiLoaderCode:
            case EfiLoaderData:
            case EfiBootServicesCode:
            case EfiBootServicesData:
            case EfiConventionalMemory:
                Desc->Attribute = Entry->Attribute;
                break;

            case EfiRuntimeServicesCode:
            case EfiRuntimeServicesData:
            case EfiPalCode:
                Desc->Attribute = Entry->Attribute | EFI_MEMORY_RUNTIME;
                break;

            default:
                Desc->Attribute = Entry->Attribute;
                break;
        }
        
        Desc = NextMemoryDescriptor(Desc, Size);
    }


    //
    //
    //

    if (MapKey) {
        *MapKey = MemoryMapKey;
    }

    Status = EFI_SUCCESS;

Done:
    ReleaseLock (&MemoryLock);
    *MemoryMapSize = BufferSize;
    return Status;
}



INTERNAL
VOID *
AllocatePoolPages (
    IN EFI_MEMORY_TYPE          PoolType,
    IN UINTN                    NoPages,
    IN UINTN                    Alignment
    )
/*++

Routine Description:

    Internal function.  Used by the pool functions to allocate pages
    to back pool allocation requests.

Arguments:

    PoolType        - The type of memory for the new pool pages

    NoPages         - No of pages to allocate

Returns:

    The allocated memory, or NULL.

--*/
{
    UINT64                      Start;
    EFI_STATUS                  Status;

    ASSERT (!EfiAtRuntime);

    //
    // Find the pages to convert
    //

    Start = FindFreePages (MAX_ADDRESS, NoPages, PoolType, Alignment);

    //
    // Convert it to boot services data
    //

    if (Start) {
        Status = ConvertPages (FALSE, Start, NoPages, PoolType);
        if (EFI_ERROR(Status)) {
            Start = 0;
        }
    }

    if (!Start) {
        DEBUG((D_ERROR, "AllocatePoolPages: failed to allocate %d pages\n", NoPages));
    }

    return (VOID *) Start;
}

INTERNAL
VOID
FreePoolPages (
    IN EFI_PHYSICAL_ADDRESS     Memory,
    IN UINTN                    NoPages
    )
/*++

Routine Description:

    Internal function.  Frees pool pages allocated via AllocatePoolPages()

Arguments:

    Memory          - The base address to free

    NoPages         - The number of pages to free


Returns:

    None

--*/
{
    ConvertPages (FALSE, Memory, NoPages, EfiConventionalMemory);
}


EFI_STATUS
SetCodeSection (
    IN EFI_PHYSICAL_ADDRESS     Base,
    IN UINTN                    NoPages,
    IN EFI_MEMORY_TYPE          MemoryType
    )
// Used by the loader to set sections to code
/*++

Routine Description:

    Used by the loader to convert code pages to code memory
    types after any fixups have been applied

Arguments:

    Base            - The base address to change the type of

    NoPages         - The number of pages to change the type of

    MemoryType      - The new memory type for the range

Returns:

    Status

--*/
{
    EFI_STATUS                  Status;


    AcquireLock (&MemoryLock);
    Status = ConvertPages (TRUE, Base, NoPages, MemoryType);
    ReleaseLock (&MemoryLock);
    return Status;
}


EFI_STATUS
TerminateMemoryMap (
    IN UINTN                    MapKey
    )
{
    EFI_STATUS                  Status;
    LIST_ENTRY                  *Link;
    MEMORY_MAP                  *Entry;

    Status = EFI_SUCCESS;

    AcquireLock (&MemoryLock);

    if (MapKey == MemoryMapKey) {

        //
        // Make sure the memory map is following all the construction rules
        // This is the last chance we will be able to display any messages on
        // the  console devices.
        //

        for (Link = MemoryMap.Flink; Link != &MemoryMap; Link = Link->Flink) {
          Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE);
          if (Entry->Attribute & EFI_MEMORY_RUNTIME) { 
            if (Entry->Type == EfiACPIReclaimMemory || Entry->Type == EfiACPIMemoryNVS) {
              DEBUG((D_ERROR, "ExitBootServices: ACPI memory entry has RUNTIME attribute set.\n"));
              ReleaseLock (&MemoryLock);
              return EFI_INVALID_PARAMETER;
            }
            if (Entry->Start & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) {
              DEBUG((D_ERROR, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
              ReleaseLock (&MemoryLock);
              return EFI_INVALID_PARAMETER;
            }
            if ((Entry->End + 1) & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) {
              DEBUG((D_ERROR, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));
              ReleaseLock (&MemoryLock);
              return EFI_INVALID_PARAMETER;
            }
          }
        }

        //
        // No going back now.  Lock memory map from changing
        //

        EfiAtRuntime = TRUE;

        //
        // The map key they gave us matches what we expect. Fall through and
        // return success. In an ideal world we would clear out all of
        // EfiBootServicesCode and EfiBootServicesData. However this function
        // is not the last one called by ExitBootServices(), so we have to
        // preserve the memory contents.
        //

    } else {

        Status = EFI_INVALID_PARAMETER;

    }

    ReleaseLock (&MemoryLock);
    return Status;
}

⌨️ 快捷键说明

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