1/** @file 2 3 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> 4 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php. 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13**/ 14 15#include <Uefi.h> 16 17#include <Library/MemoryAllocationLib.h> 18#include <Library/UefiBootServicesTableLib.h> 19#include <Library/BaseMemoryLib.h> 20#include <Library/DebugLib.h> 21#include <Library/QemuFwCfgLib.h> 22#include <Protocol/LockBox.h> 23#include <LockBoxLib.h> 24 25/** 26 Allocate memory below 4G memory address. 27 28 This function allocates memory below 4G memory address. 29 30 @param MemoryType Memory type of memory to allocate. 31 @param Size Size of memory to allocate. 32 33 @return Allocated address for output. 34 35**/ 36STATIC 37VOID * 38AllocateMemoryBelow4G ( 39 IN EFI_MEMORY_TYPE MemoryType, 40 IN UINTN Size 41 ) 42{ 43 UINTN Pages; 44 EFI_PHYSICAL_ADDRESS Address; 45 EFI_STATUS Status; 46 VOID* Buffer; 47 UINTN AllocRemaining; 48 49 Pages = EFI_SIZE_TO_PAGES (Size); 50 Address = 0xffffffff; 51 52 // 53 // Since we need to use gBS->AllocatePages to get a buffer below 54 // 4GB, there is a good chance that space will be wasted for very 55 // small allocation. We keep track of unused portions of the page 56 // allocations, and use these to allocate memory for small buffers. 57 // 58 ASSERT (mLockBoxGlobal->Signature == LOCK_BOX_GLOBAL_SIGNATURE); 59 if ((UINTN) mLockBoxGlobal->SubPageRemaining >= Size) { 60 Buffer = (VOID*)(UINTN) mLockBoxGlobal->SubPageBuffer; 61 mLockBoxGlobal->SubPageBuffer += (UINT32) Size; 62 mLockBoxGlobal->SubPageRemaining -= (UINT32) Size; 63 return Buffer; 64 } 65 66 Status = gBS->AllocatePages ( 67 AllocateMaxAddress, 68 MemoryType, 69 Pages, 70 &Address 71 ); 72 if (EFI_ERROR (Status)) { 73 return NULL; 74 } 75 76 Buffer = (VOID *) (UINTN) Address; 77 ZeroMem (Buffer, EFI_PAGES_TO_SIZE (Pages)); 78 79 AllocRemaining = EFI_PAGES_TO_SIZE (Pages) - Size; 80 if (AllocRemaining > (UINTN) mLockBoxGlobal->SubPageRemaining) { 81 mLockBoxGlobal->SubPageBuffer = (UINT32) (Address + Size); 82 mLockBoxGlobal->SubPageRemaining = (UINT32) AllocRemaining; 83 } 84 85 return Buffer; 86} 87 88 89/** 90 Allocates a buffer of type EfiACPIMemoryNVS. 91 92 Allocates the number bytes specified by AllocationSize of type 93 EfiACPIMemoryNVS and returns a pointer to the allocated buffer. 94 If AllocationSize is 0, then a valid buffer of 0 size is 95 returned. If there is not enough memory remaining to satisfy 96 the request, then NULL is returned. 97 98 @param AllocationSize The number of bytes to allocate. 99 100 @return A pointer to the allocated buffer or NULL if allocation fails. 101 102**/ 103VOID * 104EFIAPI 105AllocateAcpiNvsPool ( 106 IN UINTN AllocationSize 107 ) 108{ 109 return AllocateMemoryBelow4G (EfiACPIMemoryNVS, AllocationSize); 110} 111 112 113EFI_STATUS 114EFIAPI 115LockBoxDxeLibInitialize ( 116 IN EFI_HANDLE ImageHandle, 117 IN EFI_SYSTEM_TABLE *SystemTable 118 ) 119{ 120 EFI_STATUS Status; 121 VOID *Interface; 122 123 Status = LockBoxLibInitialize (); 124 if (!EFI_ERROR (Status)) { 125 if (QemuFwCfgS3Enabled ()) { 126 // 127 // When S3 enabled, the first driver run with this library linked will 128 // have this library constructor to install LockBox protocol on the 129 // ImageHandle. As other drivers may have gEfiLockBoxProtocolGuid 130 // dependency, the first driver should run before them. 131 // 132 Status = gBS->LocateProtocol (&gEfiLockBoxProtocolGuid, NULL, &Interface); 133 if (EFI_ERROR (Status)) { 134 Status = gBS->InstallProtocolInterface ( 135 &ImageHandle, 136 &gEfiLockBoxProtocolGuid, 137 EFI_NATIVE_INTERFACE, 138 NULL 139 ); 140 ASSERT_EFI_ERROR (Status); 141 } 142 } 143 } 144 145 return Status; 146} 147