1 /** @file
2   Implementation of the 6 PEI Ffs (FV) APIs in library form.
3 
4   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
5 
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include <PiPei.h>
11 
12 #include <Library/BaseLib.h>
13 #include <Library/BaseMemoryLib.h>
14 #include <Library/PrePiLib.h>
15 #include <Library/DebugLib.h>
16 
17 
18 
19 /**
20   Allocates one or more 4KB pages of type EfiBootServicesData.
21 
22   Allocates the number of 4KB pages of MemoryType and returns a pointer to the
23   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
24   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
25   returned.
26 
27   @param  Pages                 The number of 4 KB pages to allocate.
28 
29   @return A pointer to the allocated buffer or NULL if allocation fails.
30 
31 **/
32 VOID *
33 EFIAPI
AllocatePages(IN UINTN Pages)34 AllocatePages (
35   IN UINTN            Pages
36   )
37 {
38   EFI_PEI_HOB_POINTERS                    Hob;
39   EFI_PHYSICAL_ADDRESS                    Offset;
40 
41   Hob.Raw = GetHobList ();
42 
43   // Check to see if on 4k boundary
44   Offset = Hob.HandoffInformationTable->EfiFreeMemoryTop & 0xFFF;
45   if (Offset != 0) {
46     // If not aligned, make the allocation aligned.
47     Hob.HandoffInformationTable->EfiFreeMemoryTop -= Offset;
48   }
49 
50   //
51   // Verify that there is sufficient memory to satisfy the allocation
52   //
53   if (Hob.HandoffInformationTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) < Hob.HandoffInformationTable->EfiFreeMemoryBottom) {
54     return 0;
55   } else {
56     //
57     // Update the PHIT to reflect the memory usage
58     //
59     Hob.HandoffInformationTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE;
60 
61     // This routine used to create a memory allocation HOB a la PEI, but that's not
62     // necessary for us.
63 
64     //
65     // Create a memory allocation HOB.
66     //
67     BuildMemoryAllocationHob (
68         Hob.HandoffInformationTable->EfiFreeMemoryTop,
69         Pages * EFI_PAGE_SIZE,
70         EfiBootServicesData
71         );
72     return (VOID *)(UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop;
73   }
74 }
75 
76 
77 /**
78   Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
79 
80   Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
81   alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
82   returned.  If there is not enough memory at the specified alignment remaining to satisfy the
83   request, then NULL is returned.
84   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
85 
86   @param  Pages                 The number of 4 KB pages to allocate.
87   @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
88                                 If Alignment is zero, then byte alignment is used.
89 
90   @return A pointer to the allocated buffer or NULL if allocation fails.
91 
92 **/
93 VOID *
94 EFIAPI
AllocateAlignedPages(IN UINTN Pages,IN UINTN Alignment)95 AllocateAlignedPages (
96   IN UINTN  Pages,
97   IN UINTN  Alignment
98   )
99 {
100   VOID    *Memory;
101   UINTN   AlignmentMask;
102 
103   //
104   // Alignment must be a power of two or zero.
105   //
106   ASSERT ((Alignment & (Alignment - 1)) == 0);
107 
108   if (Pages == 0) {
109     return NULL;
110   }
111   //
112   // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
113   //
114   ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment)));
115   //
116   // We would rather waste some memory to save PEI code size.
117   //
118   Memory = (VOID *)(UINTN)AllocatePages (Pages + EFI_SIZE_TO_PAGES (Alignment));
119   if (Alignment == 0) {
120     AlignmentMask = Alignment;
121   } else {
122     AlignmentMask = Alignment - 1;
123   }
124   return (VOID *) (UINTN) (((UINTN) Memory + AlignmentMask) & ~AlignmentMask);
125 }
126 
127 
128 /**
129   Frees one or more 4KB pages that were previously allocated with one of the page allocation
130   functions in the Memory Allocation Library.
131 
132   Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer
133   must have been allocated on a previous call to the page allocation services of the Memory
134   Allocation Library.  If it is not possible to free allocated pages, then this function will
135   perform no actions.
136 
137   If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
138   then ASSERT().
139   If Pages is zero, then ASSERT().
140 
141   @param  Buffer                Pointer to the buffer of pages to free.
142   @param  Pages                 The number of 4 KB pages to free.
143 
144 **/
145 VOID
146 EFIAPI
FreePages(IN VOID * Buffer,IN UINTN Pages)147 FreePages (
148   IN VOID   *Buffer,
149   IN UINTN  Pages
150   )
151 {
152   // For now, we do not support the ability to free pages in the PrePei Memory Allocator.
153   // The allocated memory is lost.
154 }
155 
156 /**
157   Allocates a buffer of type EfiBootServicesData.
158 
159   Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
160   pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
161   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
162 
163   @param  AllocationSize        The number of bytes to allocate.
164 
165   @return A pointer to the allocated buffer or NULL if allocation fails.
166 
167 **/
168 VOID *
169 EFIAPI
AllocatePool(IN UINTN AllocationSize)170 AllocatePool (
171   IN UINTN  AllocationSize
172   )
173 {
174   EFI_HOB_MEMORY_POOL      *Hob;
175 
176   Hob = GetHobList ();
177 
178 
179   //
180   // Verify that there is sufficient memory to satisfy the allocation
181   //
182   if (AllocationSize > 0x10000) {
183     // Please call AllcoatePages for big allocations
184     return 0;
185   } else {
186 
187     Hob = (EFI_HOB_MEMORY_POOL *)CreateHob (EFI_HOB_TYPE_MEMORY_POOL, (UINT16)(sizeof (EFI_HOB_TYPE_MEMORY_POOL) + AllocationSize));
188     return (VOID *)(Hob + 1);
189   }
190 }
191 
192 /**
193   Allocates and zeros a buffer of type EfiBootServicesData.
194 
195   Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
196   buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
197   valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
198   request, then NULL is returned.
199 
200   @param  AllocationSize        The number of bytes to allocate and zero.
201 
202   @return A pointer to the allocated buffer or NULL if allocation fails.
203 
204 **/
205 VOID *
206 EFIAPI
AllocateZeroPool(IN UINTN AllocationSize)207 AllocateZeroPool (
208   IN UINTN  AllocationSize
209   )
210 {
211   VOID *Buffer;
212 
213   Buffer = AllocatePool (AllocationSize);
214   if (Buffer == NULL) {
215     return NULL;
216   }
217 
218   ZeroMem (Buffer, AllocationSize);
219 
220   return Buffer;
221 }
222 
223 /**
224   Frees a buffer that was previously allocated with one of the pool allocation functions in the
225   Memory Allocation Library.
226 
227   Frees the buffer specified by Buffer.  Buffer must have been allocated on a previous call to the
228   pool allocation services of the Memory Allocation Library.  If it is not possible to free pool
229   resources, then this function will perform no actions.
230 
231   If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
232   then ASSERT().
233 
234   @param  Buffer                Pointer to the buffer to free.
235 
236 **/
237 VOID
238 EFIAPI
FreePool(IN VOID * Buffer)239 FreePool (
240   IN VOID   *Buffer
241   )
242 {
243   // Not implemented yet
244 }
245