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