1 /** @file
2   Support routines for memory allocation routines based
3   on DxeCore Memory Allocation services for DxeCore,
4   with memory profile support.
5 
6   Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
7   SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9 **/
10 
11 
12 #include <PiDxe.h>
13 
14 
15 #include <Library/MemoryAllocationLib.h>
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/DebugLib.h>
18 #include "DxeCoreMemoryAllocationServices.h"
19 
20 #include <Library/MemoryProfileLib.h>
21 
22 /**
23   Allocates one or more 4KB pages of a certain memory type.
24 
25   Allocates the number of 4KB pages of a certain memory type and returns a pointer to the allocated
26   buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL is returned.
27   If there is not enough memory remaining to satisfy the request, then NULL is returned.
28 
29   @param  MemoryType            The type of memory to allocate.
30   @param  Pages                 The number of 4 KB pages to allocate.
31 
32   @return A pointer to the allocated buffer or NULL if allocation fails.
33 
34 **/
35 VOID *
InternalAllocatePages(IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages)36 InternalAllocatePages (
37   IN EFI_MEMORY_TYPE  MemoryType,
38   IN UINTN            Pages
39   )
40 {
41   EFI_STATUS            Status;
42   EFI_PHYSICAL_ADDRESS  Memory;
43 
44   if (Pages == 0) {
45     return NULL;
46   }
47 
48   Status = CoreAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);
49   if (EFI_ERROR (Status)) {
50     return NULL;
51   }
52   return (VOID *) (UINTN) Memory;
53 }
54 
55 /**
56   Allocates one or more 4KB pages of type EfiBootServicesData.
57 
58   Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the
59   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
60   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
61   returned.
62 
63   @param  Pages                 The number of 4 KB pages to allocate.
64 
65   @return A pointer to the allocated buffer or NULL if allocation fails.
66 
67 **/
68 VOID *
69 EFIAPI
AllocatePages(IN UINTN Pages)70 AllocatePages (
71   IN UINTN  Pages
72   )
73 {
74   VOID  *Buffer;
75 
76   Buffer = InternalAllocatePages (EfiBootServicesData, Pages);
77   if (Buffer != NULL) {
78     MemoryProfileLibRecord (
79       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
80       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_PAGES,
81       EfiBootServicesData,
82       Buffer,
83       EFI_PAGES_TO_SIZE (Pages),
84       NULL
85       );
86   }
87   return Buffer;
88 }
89 
90 /**
91   Allocates one or more 4KB pages of type EfiRuntimeServicesData.
92 
93   Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
94   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
95   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
96   returned.
97 
98   @param  Pages                 The number of 4 KB pages to allocate.
99 
100   @return A pointer to the allocated buffer or NULL if allocation fails.
101 
102 **/
103 VOID *
104 EFIAPI
AllocateRuntimePages(IN UINTN Pages)105 AllocateRuntimePages (
106   IN UINTN  Pages
107   )
108 {
109   VOID  *Buffer;
110 
111   Buffer = InternalAllocatePages (EfiRuntimeServicesData, Pages);
112   if (Buffer != NULL) {
113     MemoryProfileLibRecord (
114       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
115       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_PAGES,
116       EfiRuntimeServicesData,
117       Buffer,
118       EFI_PAGES_TO_SIZE (Pages),
119       NULL
120       );
121   }
122   return Buffer;
123 }
124 
125 /**
126   Allocates one or more 4KB pages of type EfiReservedMemoryType.
127 
128   Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the
129   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
130   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
131   returned.
132 
133   @param  Pages                 The number of 4 KB pages to allocate.
134 
135   @return A pointer to the allocated buffer or NULL if allocation fails.
136 
137 **/
138 VOID *
139 EFIAPI
AllocateReservedPages(IN UINTN Pages)140 AllocateReservedPages (
141   IN UINTN  Pages
142   )
143 {
144   VOID  *Buffer;
145 
146   Buffer = InternalAllocatePages (EfiReservedMemoryType, Pages);
147   if (Buffer != NULL) {
148     MemoryProfileLibRecord (
149       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
150       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_PAGES,
151       EfiReservedMemoryType,
152       Buffer,
153       EFI_PAGES_TO_SIZE (Pages),
154       NULL
155       );
156   }
157   return Buffer;
158 }
159 
160 /**
161   Frees one or more 4KB pages that were previously allocated with one of the page allocation
162   functions in the Memory Allocation Library.
163 
164   Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer
165   must have been allocated on a previous call to the page allocation services of the Memory
166   Allocation Library.  If it is not possible to free allocated pages, then this function will
167   perform no actions.
168 
169   If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
170   then ASSERT().
171   If Pages is zero, then ASSERT().
172 
173   @param  Buffer                Pointer to the buffer of pages to free.
174   @param  Pages                 The number of 4 KB pages to free.
175 
176 **/
177 VOID
178 EFIAPI
FreePages(IN VOID * Buffer,IN UINTN Pages)179 FreePages (
180   IN VOID   *Buffer,
181   IN UINTN  Pages
182   )
183 {
184   EFI_STATUS  Status;
185 
186   ASSERT (Pages != 0);
187   Status = CoreFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
188   ASSERT_EFI_ERROR (Status);
189 }
190 
191 /**
192   Allocates one or more 4KB pages of a certain memory type at a specified alignment.
193 
194   Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment
195   specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is returned.
196   If there is not enough memory at the specified alignment remaining to satisfy the request, then
197   NULL is returned.
198   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
199   If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
200 
201   @param  MemoryType            The type of memory to allocate.
202   @param  Pages                 The number of 4 KB pages to allocate.
203   @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
204                                 If Alignment is zero, then byte alignment is used.
205 
206   @return A pointer to the allocated buffer or NULL if allocation fails.
207 
208 **/
209 VOID *
InternalAllocateAlignedPages(IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,IN UINTN Alignment)210 InternalAllocateAlignedPages (
211   IN EFI_MEMORY_TYPE  MemoryType,
212   IN UINTN            Pages,
213   IN UINTN            Alignment
214   )
215 {
216   EFI_STATUS            Status;
217   EFI_PHYSICAL_ADDRESS  Memory;
218   UINTN                 AlignedMemory;
219   UINTN                 AlignmentMask;
220   UINTN                 UnalignedPages;
221   UINTN                 RealPages;
222 
223   //
224   // Alignment must be a power of two or zero.
225   //
226   ASSERT ((Alignment & (Alignment - 1)) == 0);
227 
228   if (Pages == 0) {
229     return NULL;
230   }
231   if (Alignment > EFI_PAGE_SIZE) {
232     //
233     // Calculate the total number of pages since alignment is larger than page size.
234     //
235     AlignmentMask  = Alignment - 1;
236     RealPages      = Pages + EFI_SIZE_TO_PAGES (Alignment);
237     //
238     // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
239     //
240     ASSERT (RealPages > Pages);
241 
242     Status         = CoreAllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory);
243     if (EFI_ERROR (Status)) {
244       return NULL;
245     }
246     AlignedMemory  = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
247     UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN) Memory);
248     if (UnalignedPages > 0) {
249       //
250       // Free first unaligned page(s).
251       //
252       Status = CoreFreePages (Memory, UnalignedPages);
253       ASSERT_EFI_ERROR (Status);
254     }
255     Memory         = AlignedMemory + EFI_PAGES_TO_SIZE (Pages);
256     UnalignedPages = RealPages - Pages - UnalignedPages;
257     if (UnalignedPages > 0) {
258       //
259       // Free last unaligned page(s).
260       //
261       Status = CoreFreePages (Memory, UnalignedPages);
262       ASSERT_EFI_ERROR (Status);
263     }
264   } else {
265     //
266     // Do not over-allocate pages in this case.
267     //
268     Status = CoreAllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory);
269     if (EFI_ERROR (Status)) {
270       return NULL;
271     }
272     AlignedMemory  = (UINTN) Memory;
273   }
274   return (VOID *) AlignedMemory;
275 }
276 
277 /**
278   Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
279 
280   Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
281   alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
282   returned.  If there is not enough memory at the specified alignment remaining to satisfy the
283   request, then NULL is returned.
284 
285   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
286   If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
287 
288   @param  Pages                 The number of 4 KB pages to allocate.
289   @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
290                                 If Alignment is zero, then byte alignment is used.
291 
292   @return A pointer to the allocated buffer or NULL if allocation fails.
293 
294 **/
295 VOID *
296 EFIAPI
AllocateAlignedPages(IN UINTN Pages,IN UINTN Alignment)297 AllocateAlignedPages (
298   IN UINTN  Pages,
299   IN UINTN  Alignment
300   )
301 {
302   VOID  *Buffer;
303 
304   Buffer = InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment);
305   if (Buffer != NULL) {
306     MemoryProfileLibRecord (
307       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
308       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_PAGES,
309       EfiBootServicesData,
310       Buffer,
311       EFI_PAGES_TO_SIZE (Pages),
312       NULL
313       );
314   }
315   return Buffer;
316 }
317 
318 /**
319   Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
320 
321   Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an
322   alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
323   returned.  If there is not enough memory at the specified alignment remaining to satisfy the
324   request, then NULL is returned.
325 
326   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
327   If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
328 
329   @param  Pages                 The number of 4 KB pages to allocate.
330   @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
331                                 If Alignment is zero, then byte alignment is used.
332 
333   @return A pointer to the allocated buffer or NULL if allocation fails.
334 
335 **/
336 VOID *
337 EFIAPI
AllocateAlignedRuntimePages(IN UINTN Pages,IN UINTN Alignment)338 AllocateAlignedRuntimePages (
339   IN UINTN  Pages,
340   IN UINTN  Alignment
341   )
342 {
343   VOID  *Buffer;
344 
345   Buffer = InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);
346   if (Buffer != NULL) {
347     MemoryProfileLibRecord (
348       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
349       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RUNTIME_PAGES,
350       EfiRuntimeServicesData,
351       Buffer,
352       EFI_PAGES_TO_SIZE (Pages),
353       NULL
354       );
355   }
356   return Buffer;
357 }
358 
359 /**
360   Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
361 
362   Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an
363   alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
364   returned.  If there is not enough memory at the specified alignment remaining to satisfy the
365   request, then NULL is returned.
366 
367   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
368   If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
369 
370   @param  Pages                 The number of 4 KB pages to allocate.
371   @param  Alignment             The requested alignment of the allocation.  Must be a power of two.
372                                 If Alignment is zero, then byte alignment is used.
373 
374   @return A pointer to the allocated buffer or NULL if allocation fails.
375 
376 **/
377 VOID *
378 EFIAPI
AllocateAlignedReservedPages(IN UINTN Pages,IN UINTN Alignment)379 AllocateAlignedReservedPages (
380   IN UINTN  Pages,
381   IN UINTN  Alignment
382   )
383 {
384   VOID  *Buffer;
385 
386   Buffer = InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment);
387   if (Buffer != NULL) {
388     MemoryProfileLibRecord (
389       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
390       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ALIGNED_RESERVED_PAGES,
391       EfiReservedMemoryType,
392       Buffer,
393       EFI_PAGES_TO_SIZE (Pages),
394       NULL
395       );
396   }
397   return Buffer;
398 }
399 
400 /**
401   Frees one or more 4KB pages that were previously allocated with one of the aligned page
402   allocation functions in the Memory Allocation Library.
403 
404   Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer
405   must have been allocated on a previous call to the aligned page allocation services of the Memory
406   Allocation Library.  If it is not possible to free allocated pages, then this function will
407   perform no actions.
408 
409   If Buffer was not allocated with an aligned page allocation function in the Memory Allocation
410   Library, then ASSERT().
411   If Pages is zero, then ASSERT().
412 
413   @param  Buffer                Pointer to the buffer of pages to free.
414   @param  Pages                 The number of 4 KB pages to free.
415 
416 **/
417 VOID
418 EFIAPI
FreeAlignedPages(IN VOID * Buffer,IN UINTN Pages)419 FreeAlignedPages (
420   IN VOID   *Buffer,
421   IN UINTN  Pages
422   )
423 {
424   EFI_STATUS  Status;
425 
426   ASSERT (Pages != 0);
427   Status = CoreFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);
428   ASSERT_EFI_ERROR (Status);
429 }
430 
431 /**
432   Allocates a buffer of a certain pool type.
433 
434   Allocates the number bytes specified by AllocationSize of a certain pool type and returns a
435   pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
436   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
437 
438   @param  MemoryType            The type of memory to allocate.
439   @param  AllocationSize        The number of bytes to allocate.
440 
441   @return A pointer to the allocated buffer or NULL if allocation fails.
442 
443 **/
444 VOID *
InternalAllocatePool(IN EFI_MEMORY_TYPE MemoryType,IN UINTN AllocationSize)445 InternalAllocatePool (
446   IN EFI_MEMORY_TYPE  MemoryType,
447   IN UINTN            AllocationSize
448   )
449 {
450   EFI_STATUS  Status;
451   VOID        *Memory;
452 
453   Memory = NULL;
454 
455   Status = CoreAllocatePool (MemoryType, AllocationSize, &Memory);
456   if (EFI_ERROR (Status)) {
457     Memory = NULL;
458   }
459   return Memory;
460 }
461 
462 /**
463   Allocates a buffer of type EfiBootServicesData.
464 
465   Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
466   pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
467   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
468 
469   @param  AllocationSize        The number of bytes to allocate.
470 
471   @return A pointer to the allocated buffer or NULL if allocation fails.
472 
473 **/
474 VOID *
475 EFIAPI
AllocatePool(IN UINTN AllocationSize)476 AllocatePool (
477   IN UINTN  AllocationSize
478   )
479 {
480   VOID  *Buffer;
481 
482   Buffer = InternalAllocatePool (EfiBootServicesData, AllocationSize);
483   if (Buffer != NULL) {
484     MemoryProfileLibRecord (
485       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
486       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_POOL,
487       EfiBootServicesData,
488       Buffer,
489       AllocationSize,
490       NULL
491       );
492   }
493   return Buffer;
494 }
495 
496 /**
497   Allocates a buffer of type EfiRuntimeServicesData.
498 
499   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns
500   a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
501   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
502 
503   @param  AllocationSize        The number of bytes to allocate.
504 
505   @return A pointer to the allocated buffer or NULL if allocation fails.
506 
507 **/
508 VOID *
509 EFIAPI
AllocateRuntimePool(IN UINTN AllocationSize)510 AllocateRuntimePool (
511   IN UINTN  AllocationSize
512   )
513 {
514   VOID  *Buffer;
515 
516   Buffer = InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
517   if (Buffer != NULL) {
518     MemoryProfileLibRecord (
519       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
520       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_POOL,
521       EfiRuntimeServicesData,
522       Buffer,
523       AllocationSize,
524       NULL
525       );
526   }
527   return Buffer;
528 }
529 
530 /**
531   Allocates a buffer of type EfiReservedMemoryType.
532 
533   Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns
534   a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
535   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
536 
537   @param  AllocationSize        The number of bytes to allocate.
538 
539   @return A pointer to the allocated buffer or NULL if allocation fails.
540 
541 **/
542 VOID *
543 EFIAPI
AllocateReservedPool(IN UINTN AllocationSize)544 AllocateReservedPool (
545   IN UINTN  AllocationSize
546   )
547 {
548   VOID  *Buffer;
549 
550   Buffer = InternalAllocatePool (EfiReservedMemoryType, AllocationSize);
551   if (Buffer != NULL) {
552     MemoryProfileLibRecord (
553       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
554       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_POOL,
555       EfiReservedMemoryType,
556       Buffer,
557       AllocationSize,
558       NULL
559       );
560   }
561   return Buffer;
562 }
563 
564 /**
565   Allocates and zeros a buffer of a certain pool type.
566 
567   Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer
568   with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a valid
569   buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the request,
570   then NULL is returned.
571 
572   @param  PoolType              The type of memory to allocate.
573   @param  AllocationSize        The number of bytes to allocate and zero.
574 
575   @return A pointer to the allocated buffer or NULL if allocation fails.
576 
577 **/
578 VOID *
InternalAllocateZeroPool(IN EFI_MEMORY_TYPE PoolType,IN UINTN AllocationSize)579 InternalAllocateZeroPool (
580   IN EFI_MEMORY_TYPE  PoolType,
581   IN UINTN            AllocationSize
582   )
583 {
584   VOID  *Memory;
585 
586   Memory = InternalAllocatePool (PoolType, AllocationSize);
587   if (Memory != NULL) {
588     Memory = ZeroMem (Memory, AllocationSize);
589   }
590   return Memory;
591 }
592 
593 /**
594   Allocates and zeros a buffer of type EfiBootServicesData.
595 
596   Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
597   buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
598   valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
599   request, then NULL is returned.
600 
601   @param  AllocationSize        The number of bytes to allocate and zero.
602 
603   @return A pointer to the allocated buffer or NULL if allocation fails.
604 
605 **/
606 VOID *
607 EFIAPI
AllocateZeroPool(IN UINTN AllocationSize)608 AllocateZeroPool (
609   IN UINTN  AllocationSize
610   )
611 {
612   VOID  *Buffer;
613 
614   Buffer = InternalAllocateZeroPool (EfiBootServicesData, AllocationSize);
615   if (Buffer != NULL) {
616     MemoryProfileLibRecord (
617       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
618       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_ZERO_POOL,
619       EfiBootServicesData,
620       Buffer,
621       AllocationSize,
622       NULL
623       );
624   }
625   return Buffer;
626 }
627 
628 /**
629   Allocates and zeros a buffer of type EfiRuntimeServicesData.
630 
631   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the
632   buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
633   valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
634   request, then NULL is returned.
635 
636   @param  AllocationSize        The number of bytes to allocate and zero.
637 
638   @return A pointer to the allocated buffer or NULL if allocation fails.
639 
640 **/
641 VOID *
642 EFIAPI
AllocateRuntimeZeroPool(IN UINTN AllocationSize)643 AllocateRuntimeZeroPool (
644   IN UINTN  AllocationSize
645   )
646 {
647   VOID  *Buffer;
648 
649   Buffer = InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);
650   if (Buffer != NULL) {
651     MemoryProfileLibRecord (
652       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
653       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_ZERO_POOL,
654       EfiRuntimeServicesData,
655       Buffer,
656       AllocationSize,
657       NULL
658       );
659   }
660   return Buffer;
661 }
662 
663 /**
664   Allocates and zeros a buffer of type EfiReservedMemoryType.
665 
666   Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the
667   buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
668   valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
669   request, then NULL is returned.
670 
671   @param  AllocationSize        The number of bytes to allocate and zero.
672 
673   @return A pointer to the allocated buffer or NULL if allocation fails.
674 
675 **/
676 VOID *
677 EFIAPI
AllocateReservedZeroPool(IN UINTN AllocationSize)678 AllocateReservedZeroPool (
679   IN UINTN  AllocationSize
680   )
681 {
682   VOID  *Buffer;
683 
684   Buffer = InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize);
685   if (Buffer != NULL) {
686     MemoryProfileLibRecord (
687       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
688       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_ZERO_POOL,
689       EfiReservedMemoryType,
690       Buffer,
691       AllocationSize,
692       NULL
693       );
694   }
695   return Buffer;
696 }
697 
698 /**
699   Copies a buffer to an allocated buffer of a certain pool type.
700 
701   Allocates the number bytes specified by AllocationSize of a certain pool type, copies
702   AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
703   allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
704   is not enough memory remaining to satisfy the request, then NULL is returned.
705   If Buffer is NULL, then ASSERT().
706   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
707 
708   @param  PoolType              The type of pool to allocate.
709   @param  AllocationSize        The number of bytes to allocate and zero.
710   @param  Buffer                The buffer to copy to the allocated buffer.
711 
712   @return A pointer to the allocated buffer or NULL if allocation fails.
713 
714 **/
715 VOID *
InternalAllocateCopyPool(IN EFI_MEMORY_TYPE PoolType,IN UINTN AllocationSize,IN CONST VOID * Buffer)716 InternalAllocateCopyPool (
717   IN EFI_MEMORY_TYPE  PoolType,
718   IN UINTN            AllocationSize,
719   IN CONST VOID       *Buffer
720   )
721 {
722   VOID  *Memory;
723 
724   ASSERT (Buffer != NULL);
725   ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));
726 
727   Memory = InternalAllocatePool (PoolType, AllocationSize);
728   if (Memory != NULL) {
729      Memory = CopyMem (Memory, Buffer, AllocationSize);
730   }
731   return Memory;
732 }
733 
734 /**
735   Copies a buffer to an allocated buffer of type EfiBootServicesData.
736 
737   Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies
738   AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
739   allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
740   is not enough memory remaining to satisfy the request, then NULL is returned.
741 
742   If Buffer is NULL, then ASSERT().
743   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
744 
745   @param  AllocationSize        The number of bytes to allocate and zero.
746   @param  Buffer                The buffer to copy to the allocated buffer.
747 
748   @return A pointer to the allocated buffer or NULL if allocation fails.
749 
750 **/
751 VOID *
752 EFIAPI
AllocateCopyPool(IN UINTN AllocationSize,IN CONST VOID * Buffer)753 AllocateCopyPool (
754   IN UINTN       AllocationSize,
755   IN CONST VOID  *Buffer
756   )
757 {
758   VOID  *NewBuffer;
759 
760   NewBuffer = InternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer);
761   if (NewBuffer != NULL) {
762     MemoryProfileLibRecord (
763       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
764       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_COPY_POOL,
765       EfiBootServicesData,
766       NewBuffer,
767       AllocationSize,
768       NULL
769       );
770   }
771   return NewBuffer;
772 }
773 
774 /**
775   Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
776 
777   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies
778   AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
779   allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
780   is not enough memory remaining to satisfy the request, then NULL is returned.
781 
782   If Buffer is NULL, then ASSERT().
783   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
784 
785   @param  AllocationSize        The number of bytes to allocate and zero.
786   @param  Buffer                The buffer to copy to the allocated buffer.
787 
788   @return A pointer to the allocated buffer or NULL if allocation fails.
789 
790 **/
791 VOID *
792 EFIAPI
AllocateRuntimeCopyPool(IN UINTN AllocationSize,IN CONST VOID * Buffer)793 AllocateRuntimeCopyPool (
794   IN UINTN       AllocationSize,
795   IN CONST VOID  *Buffer
796   )
797 {
798   VOID  *NewBuffer;
799 
800   NewBuffer = InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
801   if (NewBuffer != NULL) {
802     MemoryProfileLibRecord (
803       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
804       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RUNTIME_COPY_POOL,
805       EfiRuntimeServicesData,
806       NewBuffer,
807       AllocationSize,
808       NULL
809       );
810   }
811   return NewBuffer;
812 }
813 
814 /**
815   Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
816 
817   Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies
818   AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
819   allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
820   is not enough memory remaining to satisfy the request, then NULL is returned.
821 
822   If Buffer is NULL, then ASSERT().
823   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
824 
825   @param  AllocationSize        The number of bytes to allocate and zero.
826   @param  Buffer                The buffer to copy to the allocated buffer.
827 
828   @return A pointer to the allocated buffer or NULL if allocation fails.
829 
830 **/
831 VOID *
832 EFIAPI
AllocateReservedCopyPool(IN UINTN AllocationSize,IN CONST VOID * Buffer)833 AllocateReservedCopyPool (
834   IN UINTN       AllocationSize,
835   IN CONST VOID  *Buffer
836   )
837 {
838   VOID  *NewBuffer;
839 
840   NewBuffer = InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer);
841   if (NewBuffer != NULL) {
842     MemoryProfileLibRecord (
843       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
844       MEMORY_PROFILE_ACTION_LIB_ALLOCATE_RESERVED_COPY_POOL,
845       EfiRuntimeServicesData,
846       NewBuffer,
847       AllocationSize,
848       NULL
849       );
850   }
851   return NewBuffer;
852 }
853 
854 /**
855   Reallocates a buffer of a specified memory type.
856 
857   Allocates and zeros the number bytes specified by NewSize from memory of the type
858   specified by PoolType.  If OldBuffer is not NULL, then the smaller of OldSize and
859   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
860   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
861   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
862   enough memory remaining to satisfy the request, then NULL is returned.
863 
864   If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
865   is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
866 
867   @param  PoolType       The type of pool to allocate.
868   @param  OldSize        The size, in bytes, of OldBuffer.
869   @param  NewSize        The size, in bytes, of the buffer to reallocate.
870   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
871                          parameter that may be NULL.
872 
873   @return A pointer to the allocated buffer or NULL if allocation fails.
874 
875 **/
876 VOID *
InternalReallocatePool(IN EFI_MEMORY_TYPE PoolType,IN UINTN OldSize,IN UINTN NewSize,IN VOID * OldBuffer OPTIONAL)877 InternalReallocatePool (
878   IN EFI_MEMORY_TYPE  PoolType,
879   IN UINTN            OldSize,
880   IN UINTN            NewSize,
881   IN VOID             *OldBuffer  OPTIONAL
882   )
883 {
884   VOID  *NewBuffer;
885 
886   NewBuffer = InternalAllocateZeroPool (PoolType, NewSize);
887   if (NewBuffer != NULL && OldBuffer != NULL) {
888     CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
889     FreePool (OldBuffer);
890   }
891   return NewBuffer;
892 }
893 
894 /**
895   Reallocates a buffer of type EfiBootServicesData.
896 
897   Allocates and zeros the number bytes specified by NewSize from memory of type
898   EfiBootServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and
899   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
900   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
901   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
902   enough memory remaining to satisfy the request, then NULL is returned.
903 
904   If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
905   is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
906 
907   @param  OldSize        The size, in bytes, of OldBuffer.
908   @param  NewSize        The size, in bytes, of the buffer to reallocate.
909   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
910                          parameter that may be NULL.
911 
912   @return A pointer to the allocated buffer or NULL if allocation fails.
913 
914 **/
915 VOID *
916 EFIAPI
ReallocatePool(IN UINTN OldSize,IN UINTN NewSize,IN VOID * OldBuffer OPTIONAL)917 ReallocatePool (
918   IN UINTN  OldSize,
919   IN UINTN  NewSize,
920   IN VOID   *OldBuffer  OPTIONAL
921   )
922 {
923   VOID  *Buffer;
924 
925   Buffer = InternalReallocatePool (EfiBootServicesData, OldSize, NewSize, OldBuffer);
926   if (Buffer != NULL) {
927     MemoryProfileLibRecord (
928       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
929       MEMORY_PROFILE_ACTION_LIB_REALLOCATE_POOL,
930       EfiBootServicesData,
931       Buffer,
932       NewSize,
933       NULL
934       );
935   }
936   return Buffer;
937 }
938 
939 /**
940   Reallocates a buffer of type EfiRuntimeServicesData.
941 
942   Allocates and zeros the number bytes specified by NewSize from memory of type
943   EfiRuntimeServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and
944   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
945   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
946   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
947   enough memory remaining to satisfy the request, then NULL is returned.
948 
949   If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
950   is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
951 
952   @param  OldSize        The size, in bytes, of OldBuffer.
953   @param  NewSize        The size, in bytes, of the buffer to reallocate.
954   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
955                          parameter that may be NULL.
956 
957   @return A pointer to the allocated buffer or NULL if allocation fails.
958 
959 **/
960 VOID *
961 EFIAPI
ReallocateRuntimePool(IN UINTN OldSize,IN UINTN NewSize,IN VOID * OldBuffer OPTIONAL)962 ReallocateRuntimePool (
963   IN UINTN  OldSize,
964   IN UINTN  NewSize,
965   IN VOID   *OldBuffer  OPTIONAL
966   )
967 {
968   VOID  *Buffer;
969 
970   Buffer = InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);
971   if (Buffer != NULL) {
972     MemoryProfileLibRecord (
973       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
974       MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RUNTIME_POOL,
975       EfiRuntimeServicesData,
976       Buffer,
977       NewSize,
978       NULL
979       );
980   }
981   return Buffer;
982 }
983 
984 /**
985   Reallocates a buffer of type EfiReservedMemoryType.
986 
987   Allocates and zeros the number bytes specified by NewSize from memory of type
988   EfiReservedMemoryType.  If OldBuffer is not NULL, then the smaller of OldSize and
989   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
990   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
991   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
992   enough memory remaining to satisfy the request, then NULL is returned.
993 
994   If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
995   is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
996 
997   @param  OldSize        The size, in bytes, of OldBuffer.
998   @param  NewSize        The size, in bytes, of the buffer to reallocate.
999   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
1000                          parameter that may be NULL.
1001 
1002   @return A pointer to the allocated buffer or NULL if allocation fails.
1003 
1004 **/
1005 VOID *
1006 EFIAPI
ReallocateReservedPool(IN UINTN OldSize,IN UINTN NewSize,IN VOID * OldBuffer OPTIONAL)1007 ReallocateReservedPool (
1008   IN UINTN  OldSize,
1009   IN UINTN  NewSize,
1010   IN VOID   *OldBuffer  OPTIONAL
1011   )
1012 {
1013   VOID  *Buffer;
1014 
1015   Buffer = InternalReallocatePool (EfiReservedMemoryType, OldSize, NewSize, OldBuffer);
1016   if (Buffer != NULL) {
1017     MemoryProfileLibRecord (
1018       (PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS(0),
1019       MEMORY_PROFILE_ACTION_LIB_REALLOCATE_RESERVED_POOL,
1020       EfiReservedMemoryType,
1021       Buffer,
1022       NewSize,
1023       NULL
1024       );
1025   }
1026   return Buffer;
1027 }
1028 
1029 /**
1030   Frees a buffer that was previously allocated with one of the pool allocation functions in the
1031   Memory Allocation Library.
1032 
1033   Frees the buffer specified by Buffer.  Buffer must have been allocated on a previous call to the
1034   pool allocation services of the Memory Allocation Library.  If it is not possible to free pool
1035   resources, then this function will perform no actions.
1036 
1037   If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
1038   then ASSERT().
1039 
1040   @param  Buffer                Pointer to the buffer to free.
1041 
1042 **/
1043 VOID
1044 EFIAPI
FreePool(IN VOID * Buffer)1045 FreePool (
1046   IN VOID   *Buffer
1047   )
1048 {
1049   EFI_STATUS    Status;
1050 
1051   Status = CoreFreePool (Buffer);
1052   ASSERT_EFI_ERROR (Status);
1053 }
1054 
1055