/** @file | |
Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <Uefi.h> | |
#include <Library/MemoryAllocationLib.h> | |
#include <Library/UefiBootServicesTableLib.h> | |
#include <Library/BaseMemoryLib.h> | |
#include <Library/DebugLib.h> | |
#include <Protocol/LockBox.h> | |
#include <LockBoxLib.h> | |
/** | |
Allocate memory below 4G memory address. | |
This function allocates memory below 4G memory address. | |
@param MemoryType Memory type of memory to allocate. | |
@param Size Size of memory to allocate. | |
@return Allocated address for output. | |
**/ | |
STATIC | |
VOID * | |
AllocateMemoryBelow4G ( | |
IN EFI_MEMORY_TYPE MemoryType, | |
IN UINTN Size | |
) | |
{ | |
UINTN Pages; | |
EFI_PHYSICAL_ADDRESS Address; | |
EFI_STATUS Status; | |
VOID *Buffer; | |
UINTN AllocRemaining; | |
Pages = EFI_SIZE_TO_PAGES (Size); | |
Address = 0xffffffff; | |
// | |
// Since we need to use gBS->AllocatePages to get a buffer below | |
// 4GB, there is a good chance that space will be wasted for very | |
// small allocation. We keep track of unused portions of the page | |
// allocations, and use these to allocate memory for small buffers. | |
// | |
ASSERT (mLockBoxGlobal->Signature == LOCK_BOX_GLOBAL_SIGNATURE); | |
if ((UINTN)mLockBoxGlobal->SubPageRemaining >= Size) { | |
Buffer = (VOID *)(UINTN)mLockBoxGlobal->SubPageBuffer; | |
mLockBoxGlobal->SubPageBuffer += (UINT32)Size; | |
mLockBoxGlobal->SubPageRemaining -= (UINT32)Size; | |
return Buffer; | |
} | |
Status = gBS->AllocatePages ( | |
AllocateMaxAddress, | |
MemoryType, | |
Pages, | |
&Address | |
); | |
if (EFI_ERROR (Status)) { | |
return NULL; | |
} | |
Buffer = (VOID *)(UINTN)Address; | |
ZeroMem (Buffer, EFI_PAGES_TO_SIZE (Pages)); | |
AllocRemaining = EFI_PAGES_TO_SIZE (Pages) - Size; | |
if (AllocRemaining > (UINTN)mLockBoxGlobal->SubPageRemaining) { | |
mLockBoxGlobal->SubPageBuffer = (UINT32)(Address + Size); | |
mLockBoxGlobal->SubPageRemaining = (UINT32)AllocRemaining; | |
} | |
return Buffer; | |
} | |
/** | |
Allocates a buffer of type EfiACPIMemoryNVS. | |
Allocates the number bytes specified by AllocationSize of type | |
EfiACPIMemoryNVS and returns a pointer to the allocated buffer. | |
If AllocationSize is 0, then a valid buffer of 0 size is | |
returned. If there is not enough memory remaining to satisfy | |
the request, then NULL is returned. | |
@param AllocationSize The number of bytes to allocate. | |
@return A pointer to the allocated buffer or NULL if allocation fails. | |
**/ | |
VOID * | |
EFIAPI | |
AllocateAcpiNvsPool ( | |
IN UINTN AllocationSize | |
) | |
{ | |
return AllocateMemoryBelow4G (EfiACPIMemoryNVS, AllocationSize); | |
} | |
EFI_STATUS | |
EFIAPI | |
LockBoxDxeLibInitialize ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
{ | |
EFI_STATUS Status; | |
VOID *Interface; | |
Status = LockBoxLibInitialize (); | |
if (!EFI_ERROR (Status)) { | |
if (PcdGetBool (PcdAcpiS3Enable)) { | |
// | |
// When S3 enabled, the first driver run with this library linked will | |
// have this library constructor to install LockBox protocol on the | |
// ImageHandle. As other drivers may have gEfiLockBoxProtocolGuid | |
// dependency, the first driver should run before them. | |
// | |
Status = gBS->LocateProtocol (&gEfiLockBoxProtocolGuid, NULL, &Interface); | |
if (EFI_ERROR (Status)) { | |
Status = gBS->InstallProtocolInterface ( | |
&ImageHandle, | |
&gEfiLockBoxProtocolGuid, | |
EFI_NATIVE_INTERFACE, | |
NULL | |
); | |
ASSERT_EFI_ERROR (Status); | |
} | |
} | |
} | |
return Status; | |
} |