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 *
AllocateMemoryBelow4G(IN EFI_MEMORY_TYPE MemoryType,IN UINTN Size)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
AllocateAcpiNvsPool(IN UINTN AllocationSize)105 AllocateAcpiNvsPool (
106   IN UINTN  AllocationSize
107   )
108 {
109   return AllocateMemoryBelow4G (EfiACPIMemoryNVS, AllocationSize);
110 }
111 
112 
113 EFI_STATUS
114 EFIAPI
LockBoxDxeLibInitialize(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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