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 **/ 36 STATIC 37 VOID * 38 AllocateMemoryBelow4G ( 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 **/ 103 VOID * 104 EFIAPI 105 AllocateAcpiNvsPool ( 106 IN UINTN AllocationSize 107 ) 108 { 109 return AllocateMemoryBelow4G (EfiACPIMemoryNVS, AllocationSize); 110 } 111 112 113 EFI_STATUS 114 EFIAPI 115 LockBoxDxeLibInitialize ( 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