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