1 /** @file
2   Support routines for memory allocation routines based
3   on boot services for Dxe phase drivers using OS malloc.
4 
5   OS malloc is used so OS based malloc debugging tools can be used.
6   If a single driver links against this lib protocols from other
7   drivers, or EFI boot services can return a buffer that needs to
8   freed using the EFI scheme. This is why the gEmuThunk->Free ()
9   can detect if the memory rang is for EFI so the right free can be
10   called.
11 
12   Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
13   Portions copyright (c) 2011, Apple Inc. All rights reserved.
14   This program and the accompanying materials
15   are licensed and made available under the terms and conditions of the BSD License
16   which accompanies this distribution.  The full text of the license may be found at
17   http://opensource.org/licenses/bsd-license.php.
18 
19   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
20   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 
22 **/
23 
24 
25 #include <Uefi.h>
26 
27 
28 #include <Library/MemoryAllocationLib.h>
29 #include <Library/UefiBootServicesTableLib.h>
30 #include <Library/BaseMemoryLib.h>
31 #include <Library/DebugLib.h>
32 #include <Library/EmuThunkLib.h>
33 
34 /**
35   Allocates one or more 4KB pages of a certain memory type.
36 
37   Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated
38   buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL is returned.
39   If there is not enough memory remaining to satisfy the request, then NULL is returned.
40 
41   @param  MemoryType            The type of memory to allocate.
42   @param  Pages                 The number of 4 KB pages to allocate.
43 
44   @return A pointer to the allocated buffer or NULL if allocation fails.
45 
46 **/
47 VOID *
InternalAllocatePages(IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages)48 InternalAllocatePages (
49   IN EFI_MEMORY_TYPE  MemoryType,
50   IN UINTN            Pages
51   )
52 {
53   EFI_STATUS            Status;
54   EFI_PHYSICAL_ADDRESS  Memory;
55 
56   if (Pages == 0) {
57     return NULL;
58   }
59 
60   return gEmuThunk->Valloc (Pages * EFI_PAGE_SIZE);
61 }
62 
63 /**
64   Allocates one or more 4KB pages of type EfiBootServicesData.
65 
66   Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the
67   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
68   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
69   returned.
70 
71   @param  Pages                 The number of 4 KB pages to allocate.
72 
73   @return A pointer to the allocated buffer or NULL if allocation fails.
74 
75 **/
76 VOID *
77 EFIAPI
AllocatePages(IN UINTN Pages)78 AllocatePages (
79   IN UINTN  Pages
80   )
81 {
82   return InternalAllocatePages (EfiBootServicesData, Pages);
83 }
84 
85 /**
86   Allocates one or more 4KB pages of type EfiRuntimeServicesData.
87 
88   Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
89   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
90   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
91   returned.
92 
93   @param  Pages                 The number of 4 KB pages to allocate.
94 
95   @return A pointer to the allocated buffer or NULL if allocation fails.
96 
97 **/
98 VOID *
99 EFIAPI
AllocateRuntimePages(IN UINTN Pages)100 AllocateRuntimePages (
101   IN UINTN  Pages
102   )
103 {
104   return InternalAllocatePages (EfiRuntimeServicesData, Pages);
105 }
106 
107 /**
108   Allocates one or more 4KB pages of type EfiReservedMemoryType.
109 
110   Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the
111   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
112   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
113   returned.
114 
115   @param  Pages                 The number of 4 KB pages to allocate.
116 
117   @return A pointer to the allocated buffer or NULL if allocation fails.
118 
119 **/
120 VOID *
121 EFIAPI
AllocateReservedPages(IN UINTN Pages)122 AllocateReservedPages (
123   IN UINTN  Pages
124   )
125 {
126   return InternalAllocatePages (EfiReservedMemoryType, Pages);
127 }
128 
129 /**
130   Frees one or more 4KB pages that were previously allocated with one of the page allocation
131   functions in the Memory Allocation Library.
132 
133   Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer
134   must have been allocated on a previous call to the page allocation services of the Memory
135   Allocation Library.  If it is not possible to free allocated pages, then this function will
136   perform no actions.
137 
138   If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
139   then ASSERT().
140   If Pages is zero, then ASSERT().
141 
142   @param  Buffer                The pointer to the buffer of pages to free.
143   @param  Pages                 The number of 4 KB pages to free.
144 
145 **/
146 VOID
147 EFIAPI
FreePages(IN VOID * Buffer,IN UINTN Pages)148 FreePages (
149   IN VOID   *Buffer,
150   IN UINTN  Pages
151   )
152 {
153   EFI_STATUS    Status;
154 
155   ASSERT (Pages != 0);
156   if (!gEmuThunk->Free (Buffer)) {
157     // The Free thunk will not free memory allocated in emulated EFI memory.
158     // The assmuption is this was allocated directly by EFI. We need this as some
159     // times protocols or EFI BootServices can return dynamically allocated buffers.
160     Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
161     ASSERT_EFI_ERROR (Status);
162   }
163 }
164 
165 /**
166   Allocates one or more 4KB pages of a certain memory type at a specified alignment.
167 
168   Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment
169   specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is returned.
170   If there is not enough memory at the specified alignment remaining to satisfy the request, then
171   NULL is returned.
172   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
173 
174   @param  MemoryType            The type of memory to allocate.
175   @param  Pages                 The number of 4 KB pages to allocate.
176   @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
177                                 If Alignment is zero, then byte alignment is used.
178 
179   @return A pointer to the allocated buffer or NULL if allocation fails.
180 
181 **/
182 VOID *
InternalAllocateAlignedPages(IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,IN UINTN Alignment)183 InternalAllocateAlignedPages (
184   IN EFI_MEMORY_TYPE  MemoryType,
185   IN UINTN            Pages,
186   IN UINTN            Alignment
187   )
188 {
189   EFI_STATUS            Status;
190   VOID                  *Memory;
191   UINTN                 AlignedMemory;
192   UINTN                 AlignmentMask;
193   UINTN                 UnalignedPages;
194   UINTN                 RealPages;
195 
196   //
197   // Alignment must be a power of two or zero.
198   //
199   ASSERT ((Alignment & (Alignment - 1)) == 0);
200 
201   if (Pages == 0) {
202     return NULL;
203   }
204   if (Alignment > EFI_PAGE_SIZE) {
205     //
206     // Caculate the total number of pages since alignment is larger than page size.
207     //
208     AlignmentMask  = Alignment - 1;
209     RealPages      = Pages + EFI_SIZE_TO_PAGES (Alignment);
210     //
211     // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
212     //
213     ASSERT (RealPages > Pages);
214 
215     Memory = gEmuThunk->Valloc (Pages * EFI_PAGE_SIZE);
216     if (Memory != NULL) {
217       return NULL;
218     }
219     AlignedMemory  = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
220     UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);
221     if (UnalignedPages > 0) {
222       //
223       // Free first unaligned page(s).
224       //
225       FreePages (Memory, UnalignedPages);
226     }
227     Memory         = (VOID *) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages));
228     UnalignedPages = RealPages - Pages - UnalignedPages;
229     if (UnalignedPages > 0) {
230       //
231       // Free last unaligned page(s).
232       //
233       FreePages (Memory, UnalignedPages);
234     }
235   } else {
236     //
237     // Do not over-allocate pages in this case.
238     //
239     Memory = gEmuThunk->Valloc (Pages * EFI_PAGE_SIZE);
240     if (Memory != NULL) {
241       return NULL;
242     }
243     AlignedMemory  = (UINTN) Memory;
244   }
245   return (VOID *) AlignedMemory;
246 }
247 
248 /**
249   Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
250 
251   Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
252   alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
253   returned.  If there is not enough memory at the specified alignment remaining to satisfy the
254   request, then NULL is returned.
255 
256   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
257 
258   @param  Pages                 The number of 4 KB pages to allocate.
259   @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
260                                 If Alignment is zero, then byte alignment is used.
261 
262   @return A pointer to the allocated buffer or NULL if allocation fails.
263 
264 **/
265 VOID *
266 EFIAPI
AllocateAlignedPages(IN UINTN Pages,IN UINTN Alignment)267 AllocateAlignedPages (
268   IN UINTN  Pages,
269   IN UINTN  Alignment
270   )
271 {
272   return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment);
273 }
274 
275 /**
276   Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
277 
278   Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an
279   alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
280   returned.  If there is not enough memory at the specified alignment remaining to satisfy the
281   request, then NULL is returned.
282 
283   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
284 
285   @param  Pages                 The number of 4 KB pages to allocate.
286   @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
287                                 If Alignment is zero, then byte alignment is used.
288 
289   @return A pointer to the allocated buffer or NULL if allocation fails.
290 
291 **/
292 VOID *
293 EFIAPI
AllocateAlignedRuntimePages(IN UINTN Pages,IN UINTN Alignment)294 AllocateAlignedRuntimePages (
295   IN UINTN  Pages,
296   IN UINTN  Alignment
297   )
298 {
299   return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);
300 }
301 
302 /**
303   Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
304 
305   Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an
306   alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
307   returned.  If there is not enough memory at the specified alignment remaining to satisfy the
308   request, then NULL is returned.
309 
310   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
311 
312   @param  Pages                 The number of 4 KB pages to allocate.
313   @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
314                                 If Alignment is zero, then byte alignment is used.
315 
316   @return A pointer to the allocated buffer or NULL if allocation fails.
317 
318 **/
319 VOID *
320 EFIAPI
AllocateAlignedReservedPages(IN UINTN Pages,IN UINTN Alignment)321 AllocateAlignedReservedPages (
322   IN UINTN  Pages,
323   IN UINTN  Alignment
324   )
325 {
326   return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment);
327 }
328 
329 /**
330   Frees one or more 4KB pages that were previously allocated with one of the aligned page
331   allocation functions in the Memory Allocation Library.
332 
333   Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer
334   must have been allocated on a previous call to the aligned page allocation services of the Memory
335   Allocation Library.  If it is not possible to free allocated pages, then this function will
336   perform no actions.
337 
338   If Buffer was not allocated with an aligned page allocation function in the Memory Allocation
339   Library, then ASSERT().
340   If Pages is zero, then ASSERT().
341 
342   @param  Buffer                The pointer to the buffer of pages to free.
343   @param  Pages                 The number of 4 KB pages to free.
344 
345 **/
346 VOID
347 EFIAPI
FreeAlignedPages(IN VOID * Buffer,IN UINTN Pages)348 FreeAlignedPages (
349   IN VOID   *Buffer,
350   IN UINTN  Pages
351   )
352 {
353   FreePages (Buffer, Pages);
354 }
355 
356 /**
357   Allocates a buffer of a certain pool type.
358 
359   Allocates the number bytes specified by AllocationSize of a certain pool type and returns a
360   pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
361   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
362 
363   @param  MemoryType            The type of memory to allocate.
364   @param  AllocationSize        The number of bytes to allocate.
365 
366   @return A pointer to the allocated buffer or NULL if allocation fails.
367 
368 **/
369 VOID *
InternalAllocatePool(IN EFI_MEMORY_TYPE MemoryType,IN UINTN AllocationSize)370 InternalAllocatePool (
371   IN EFI_MEMORY_TYPE  MemoryType,
372   IN UINTN            AllocationSize
373   )
374 {
375   return gEmuThunk->Malloc (AllocationSize);
376 }
377 
378 /**
379   Allocates a buffer of type EfiBootServicesData.
380 
381   Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
382   pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
383   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
384 
385   @param  AllocationSize        The number of bytes to allocate.
386 
387   @return A pointer to the allocated buffer or NULL if allocation fails.
388 
389 **/
390 VOID *
391 EFIAPI
AllocatePool(IN UINTN AllocationSize)392 AllocatePool (
393   IN UINTN  AllocationSize
394   )
395 {
396   return InternalAllocatePool (EfiBootServicesData, AllocationSize);
397 }
398 
399 /**
400   Allocates a buffer of type EfiRuntimeServicesData.
401 
402   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns
403   a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
404   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
405 
406   @param  AllocationSize        The number of bytes to allocate.
407 
408   @return A pointer to the allocated buffer or NULL if allocation fails.
409 
410 **/
411 VOID *
412 EFIAPI
AllocateRuntimePool(IN UINTN AllocationSize)413 AllocateRuntimePool (
414   IN UINTN  AllocationSize
415   )
416 {
417   return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
418 }
419 
420 /**
421   Allocates a buffer of type EfiReservedMemoryType.
422 
423   Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns
424   a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
425   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
426 
427   @param  AllocationSize        The number of bytes to allocate.
428 
429   @return A pointer to the allocated buffer or NULL if allocation fails.
430 
431 **/
432 VOID *
433 EFIAPI
AllocateReservedPool(IN UINTN AllocationSize)434 AllocateReservedPool (
435   IN UINTN  AllocationSize
436   )
437 {
438   return InternalAllocatePool (EfiReservedMemoryType, AllocationSize);
439 }
440 
441 /**
442   Allocates and zeros a buffer of a certain pool type.
443 
444   Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer
445   with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a valid
446   buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the request,
447   then NULL is returned.
448 
449   @param  PoolType              The type of memory to allocate.
450   @param  AllocationSize        The number of bytes to allocate and zero.
451 
452   @return A pointer to the allocated buffer or NULL if allocation fails.
453 
454 **/
455 VOID *
InternalAllocateZeroPool(IN EFI_MEMORY_TYPE PoolType,IN UINTN AllocationSize)456 InternalAllocateZeroPool (
457   IN EFI_MEMORY_TYPE  PoolType,
458   IN UINTN            AllocationSize
459   )
460 {
461   VOID  *Memory;
462 
463   Memory = InternalAllocatePool (PoolType, AllocationSize);
464   if (Memory != NULL) {
465     Memory = ZeroMem (Memory, AllocationSize);
466   }
467   return Memory;
468 }
469 
470 /**
471   Allocates and zeros a buffer of type EfiBootServicesData.
472 
473   Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
474   buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
475   valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
476   request, then NULL is returned.
477 
478   @param  AllocationSize        The number of bytes to allocate and zero.
479 
480   @return A pointer to the allocated buffer or NULL if allocation fails.
481 
482 **/
483 VOID *
484 EFIAPI
AllocateZeroPool(IN UINTN AllocationSize)485 AllocateZeroPool (
486   IN UINTN  AllocationSize
487   )
488 {
489   return InternalAllocateZeroPool (EfiBootServicesData, AllocationSize);
490 }
491 
492 /**
493   Allocates and zeros a buffer of type EfiRuntimeServicesData.
494 
495   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the
496   buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
497   valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
498   request, then NULL is returned.
499 
500   @param  AllocationSize        The number of bytes to allocate and zero.
501 
502   @return A pointer to the allocated buffer or NULL if allocation fails.
503 
504 **/
505 VOID *
506 EFIAPI
AllocateRuntimeZeroPool(IN UINTN AllocationSize)507 AllocateRuntimeZeroPool (
508   IN UINTN  AllocationSize
509   )
510 {
511   return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);
512 }
513 
514 /**
515   Allocates and zeros a buffer of type EfiReservedMemoryType.
516 
517   Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the
518   buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
519   valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
520   request, then NULL is returned.
521 
522   @param  AllocationSize        The number of bytes to allocate and zero.
523 
524   @return A pointer to the allocated buffer or NULL if allocation fails.
525 
526 **/
527 VOID *
528 EFIAPI
AllocateReservedZeroPool(IN UINTN AllocationSize)529 AllocateReservedZeroPool (
530   IN UINTN  AllocationSize
531   )
532 {
533   return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize);
534 }
535 
536 /**
537   Copies a buffer to an allocated buffer of a certain pool type.
538 
539   Allocates the number bytes specified by AllocationSize of a certain pool type, copies
540   AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
541   allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
542   is not enough memory remaining to satisfy the request, then NULL is returned.
543   If Buffer is NULL, then ASSERT().
544   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
545 
546   @param  PoolType              The type of pool to allocate.
547   @param  AllocationSize        The number of bytes to allocate and zero.
548   @param  Buffer                The buffer to copy to the allocated buffer.
549 
550   @return A pointer to the allocated buffer or NULL if allocation fails.
551 
552 **/
553 VOID *
InternalAllocateCopyPool(IN EFI_MEMORY_TYPE PoolType,IN UINTN AllocationSize,IN CONST VOID * Buffer)554 InternalAllocateCopyPool (
555   IN EFI_MEMORY_TYPE  PoolType,
556   IN UINTN            AllocationSize,
557   IN CONST VOID       *Buffer
558   )
559 {
560   VOID  *Memory;
561 
562   ASSERT (Buffer != NULL);
563   ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));
564 
565   Memory = InternalAllocatePool (PoolType, AllocationSize);
566   if (Memory != NULL) {
567      Memory = CopyMem (Memory, Buffer, AllocationSize);
568   }
569   return Memory;
570 }
571 
572 /**
573   Copies a buffer to an allocated buffer of type EfiBootServicesData.
574 
575   Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies
576   AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
577   allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
578   is not enough memory remaining to satisfy the request, then NULL is returned.
579 
580   If Buffer is NULL, then ASSERT().
581   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
582 
583   @param  AllocationSize        The number of bytes to allocate and zero.
584   @param  Buffer                The buffer to copy to the allocated buffer.
585 
586   @return A pointer to the allocated buffer or NULL if allocation fails.
587 
588 **/
589 VOID *
590 EFIAPI
AllocateCopyPool(IN UINTN AllocationSize,IN CONST VOID * Buffer)591 AllocateCopyPool (
592   IN UINTN       AllocationSize,
593   IN CONST VOID  *Buffer
594   )
595 {
596   return InternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer);
597 }
598 
599 /**
600   Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
601 
602   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies
603   AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
604   allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
605   is not enough memory remaining to satisfy the request, then NULL is returned.
606 
607   If Buffer is NULL, then ASSERT().
608   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
609 
610   @param  AllocationSize        The number of bytes to allocate and zero.
611   @param  Buffer                The buffer to copy to the allocated buffer.
612 
613   @return A pointer to the allocated buffer or NULL if allocation fails.
614 
615 **/
616 VOID *
617 EFIAPI
AllocateRuntimeCopyPool(IN UINTN AllocationSize,IN CONST VOID * Buffer)618 AllocateRuntimeCopyPool (
619   IN UINTN       AllocationSize,
620   IN CONST VOID  *Buffer
621   )
622 {
623   return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
624 }
625 
626 /**
627   Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
628 
629   Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies
630   AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
631   allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
632   is not enough memory remaining to satisfy the request, then NULL is returned.
633 
634   If Buffer is NULL, then ASSERT().
635   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
636 
637   @param  AllocationSize        The number of bytes to allocate and zero.
638   @param  Buffer                The buffer to copy to the allocated buffer.
639 
640   @return A pointer to the allocated buffer or NULL if allocation fails.
641 
642 **/
643 VOID *
644 EFIAPI
AllocateReservedCopyPool(IN UINTN AllocationSize,IN CONST VOID * Buffer)645 AllocateReservedCopyPool (
646   IN UINTN       AllocationSize,
647   IN CONST VOID  *Buffer
648   )
649 {
650   return InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer);
651 }
652 
653 /**
654   Reallocates a buffer of a specified memory type.
655 
656   Allocates and zeros the number bytes specified by NewSize from memory of the type
657   specified by PoolType.  If OldBuffer is not NULL, then the smaller of OldSize and
658   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
659   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
660   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
661   enough memory remaining to satisfy the request, then NULL is returned.
662 
663   If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
664   is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
665 
666   @param  PoolType       The type of pool to allocate.
667   @param  OldSize        The size, in bytes, of OldBuffer.
668   @param  NewSize        The size, in bytes, of the buffer to reallocate.
669   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
670                          parameter that may be NULL.
671 
672   @return A pointer to the allocated buffer or NULL if allocation fails.
673 
674 **/
675 VOID *
InternalReallocatePool(IN EFI_MEMORY_TYPE PoolType,IN UINTN OldSize,IN UINTN NewSize,IN VOID * OldBuffer OPTIONAL)676 InternalReallocatePool (
677   IN EFI_MEMORY_TYPE  PoolType,
678   IN UINTN            OldSize,
679   IN UINTN            NewSize,
680   IN VOID             *OldBuffer  OPTIONAL
681   )
682 {
683   VOID  *NewBuffer;
684 
685   NewBuffer = InternalAllocateZeroPool (PoolType, NewSize);
686   if (NewBuffer != NULL && OldBuffer != NULL) {
687     CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
688     FreePool (OldBuffer);
689   }
690   return NewBuffer;
691 }
692 
693 /**
694   Reallocates a buffer of type EfiBootServicesData.
695 
696   Allocates and zeros the number bytes specified by NewSize from memory of type
697   EfiBootServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and
698   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
699   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
700   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
701   enough memory remaining to satisfy the request, then NULL is returned.
702 
703   If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
704   is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
705 
706   @param  OldSize        The size, in bytes, of OldBuffer.
707   @param  NewSize        The size, in bytes, of the buffer to reallocate.
708   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
709                          parameter that may be NULL.
710 
711   @return A pointer to the allocated buffer or NULL if allocation fails.
712 
713 **/
714 VOID *
715 EFIAPI
ReallocatePool(IN UINTN OldSize,IN UINTN NewSize,IN VOID * OldBuffer OPTIONAL)716 ReallocatePool (
717   IN UINTN  OldSize,
718   IN UINTN  NewSize,
719   IN VOID   *OldBuffer  OPTIONAL
720   )
721 {
722   return InternalReallocatePool (EfiBootServicesData, OldSize, NewSize, OldBuffer);
723 }
724 
725 /**
726   Reallocates a buffer of type EfiRuntimeServicesData.
727 
728   Allocates and zeros the number bytes specified by NewSize from memory of type
729   EfiRuntimeServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and
730   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
731   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
732   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
733   enough memory remaining to satisfy the request, then NULL is returned.
734 
735   If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
736   is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
737 
738   @param  OldSize        The size, in bytes, of OldBuffer.
739   @param  NewSize        The size, in bytes, of the buffer to reallocate.
740   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
741                          parameter that may be NULL.
742 
743   @return A pointer to the allocated buffer or NULL if allocation fails.
744 
745 **/
746 VOID *
747 EFIAPI
ReallocateRuntimePool(IN UINTN OldSize,IN UINTN NewSize,IN VOID * OldBuffer OPTIONAL)748 ReallocateRuntimePool (
749   IN UINTN  OldSize,
750   IN UINTN  NewSize,
751   IN VOID   *OldBuffer  OPTIONAL
752   )
753 {
754   return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);
755 }
756 
757 /**
758   Reallocates a buffer of type EfiReservedMemoryType.
759 
760   Allocates and zeros the number bytes specified by NewSize from memory of type
761   EfiReservedMemoryType.  If OldBuffer is not NULL, then the smaller of OldSize and
762   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
763   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
764   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
765   enough memory remaining to satisfy the request, then NULL is returned.
766 
767   If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
768   is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
769 
770   @param  OldSize        The size, in bytes, of OldBuffer.
771   @param  NewSize        The size, in bytes, of the buffer to reallocate.
772   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
773                          parameter that may be NULL.
774 
775   @return A pointer to the allocated buffer or NULL if allocation fails.
776 
777 **/
778 VOID *
779 EFIAPI
ReallocateReservedPool(IN UINTN OldSize,IN UINTN NewSize,IN VOID * OldBuffer OPTIONAL)780 ReallocateReservedPool (
781   IN UINTN  OldSize,
782   IN UINTN  NewSize,
783   IN VOID   *OldBuffer  OPTIONAL
784   )
785 {
786   return InternalReallocatePool (EfiReservedMemoryType, OldSize, NewSize, OldBuffer);
787 }
788 
789 /**
790   Frees a buffer that was previously allocated with one of the pool allocation functions in the
791   Memory Allocation Library.
792 
793   Frees the buffer specified by Buffer.  Buffer must have been allocated on a previous call to the
794   pool allocation services of the Memory Allocation Library.  If it is not possible to free pool
795   resources, then this function will perform no actions.
796 
797   If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
798   then ASSERT().
799 
800   @param  Buffer                The pointer to the buffer to free.
801 
802 **/
803 VOID
804 EFIAPI
FreePool(IN VOID * Buffer)805 FreePool (
806   IN VOID   *Buffer
807   )
808 {
809   EFI_STATUS    Status;
810 
811   if (!gEmuThunk->Free (Buffer)) {
812     // The Free thunk will not free memory allocated in emulated EFI memory.
813     // The assmuption is this was allocated directly by EFI. We need this as some
814     // times protocols or EFI BootServices can return dynamically allocated buffers.
815     Status = gBS->FreePool (Buffer);
816     ASSERT_EFI_ERROR (Status);
817   }
818 }
819 
820