• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Support routines for memory allocation routines
3   based on PeiService for PEI phase drivers.
4 
5   Copyright (c) 2006 - 2015, 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 <PiPei.h>
18 
19 
20 #include <Library/MemoryAllocationLib.h>
21 #include <Library/PeiServicesLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/DebugLib.h>
24 #include <Library/HobLib.h>
25 
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 = PeiServicesAllocatePages (MemoryType, Pages, &Memory);
54   if (EFI_ERROR (Status)) {
55     return NULL;
56   }
57 
58   return (VOID *) (UINTN) Memory;
59 }
60 
61 /**
62   Allocates one or more 4KB pages of type EfiBootServicesData.
63 
64   Allocates the number of 4KB pages of type EfiBootServicesData and returns a pointer to the
65   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
66   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
67   returned.
68 
69   @param  Pages                 The number of 4 KB pages to allocate.
70 
71   @return A pointer to the allocated buffer or NULL if allocation fails.
72 
73 **/
74 VOID *
75 EFIAPI
AllocatePages(IN UINTN Pages)76 AllocatePages (
77   IN UINTN  Pages
78   )
79 {
80   return InternalAllocatePages (EfiBootServicesData, Pages);
81 }
82 
83 /**
84   Allocates one or more 4KB pages of type EfiRuntimeServicesData.
85 
86   Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
87   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
88   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
89   returned.
90 
91   @param  Pages                 The number of 4 KB pages to allocate.
92 
93   @return A pointer to the allocated buffer or NULL if allocation fails.
94 
95 **/
96 VOID *
97 EFIAPI
AllocateRuntimePages(IN UINTN Pages)98 AllocateRuntimePages (
99   IN UINTN  Pages
100   )
101 {
102   return InternalAllocatePages (EfiRuntimeServicesData, Pages);
103 }
104 
105 /**
106   Allocates one or more 4KB pages of type EfiReservedMemoryType.
107 
108   Allocates the number of 4KB pages of type EfiReservedMemoryType and returns a pointer to the
109   allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL
110   is returned.  If there is not enough memory remaining to satisfy the request, then NULL is
111   returned.
112 
113   @param  Pages                 The number of 4 KB pages to allocate.
114 
115   @return A pointer to the allocated buffer or NULL if allocation fails.
116 
117 **/
118 VOID *
119 EFIAPI
AllocateReservedPages(IN UINTN Pages)120 AllocateReservedPages (
121   IN UINTN  Pages
122   )
123 {
124   return InternalAllocatePages (EfiReservedMemoryType, Pages);
125 }
126 
127 /**
128   Frees one or more 4KB pages that were previously allocated with one of the page allocation
129   functions in the Memory Allocation Library.
130 
131   Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer
132   must have been allocated on a previous call to the page allocation services of the Memory
133   Allocation Library.  If it is not possible to free allocated pages, then this function will
134   perform no actions.
135 
136   If Buffer was not allocated with a page allocation function in the Memory Allocation Library,
137   then ASSERT().
138   If Pages is zero, then ASSERT().
139 
140   @param  Buffer                The pointer to the buffer of pages to free.
141   @param  Pages                 The number of 4 KB pages to free.
142 
143 **/
144 VOID
145 EFIAPI
FreePages(IN VOID * Buffer,IN UINTN Pages)146 FreePages (
147   IN VOID   *Buffer,
148   IN UINTN  Pages
149   )
150 {
151   ASSERT (Pages != 0);
152   //
153   // PEI phase does not support to free pages, so leave it as NOP.
154   //
155 }
156 
157 /**
158   Allocates one or more 4KB pages of a certain memory type at a specified alignment.
159 
160   Allocates the number of 4KB pages specified by Pages of a certain memory type with an alignment
161   specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is returned.
162   If there is not enough memory at the specified alignment remaining to satisfy the request, then
163   NULL is returned.
164   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
165   If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
166 
167   @param  MemoryType            The type of memory to allocate.
168   @param  Pages                 The number of 4 KB pages to allocate.
169   @param  Alignment             The requested alignment of the allocation.
170                                 Must be a power of two.
171                                 If Alignment is zero, then byte alignment is used.
172 
173   @return A pointer to the allocated buffer or NULL if allocation fails.
174 
175 **/
176 VOID *
InternalAllocateAlignedPages(IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,IN UINTN Alignment)177 InternalAllocateAlignedPages (
178   IN EFI_MEMORY_TYPE  MemoryType,
179   IN UINTN            Pages,
180   IN UINTN            Alignment
181   )
182 {
183   EFI_PHYSICAL_ADDRESS   Memory;
184   EFI_PHYSICAL_ADDRESS   AlignedMemory;
185   EFI_PEI_HOB_POINTERS   Hob;
186   BOOLEAN                SkipBeforeMemHob;
187   BOOLEAN                SkipAfterMemHob;
188   EFI_PHYSICAL_ADDRESS   HobBaseAddress;
189   UINT64                 HobLength;
190   EFI_MEMORY_TYPE        HobMemoryType;
191   UINTN                  TotalPages;
192 
193   //
194   // Alignment must be a power of two or zero.
195   //
196   ASSERT ((Alignment & (Alignment - 1)) == 0);
197 
198   if (Pages == 0) {
199     return NULL;
200   }
201   //
202   // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
203   //
204   ASSERT (Pages <= (MAX_ADDRESS - EFI_SIZE_TO_PAGES (Alignment)));
205 
206   //
207   // We would rather waste some memory to save PEI code size.
208   // meaning in addition to the requested size for the aligned mem,
209   // we simply reserve an overhead memory equal to Alignmemt(page-aligned), no matter what.
210   // The overhead mem size could be reduced later with more involved malloc mechanisms
211   // (e.g., somthing that can detect the alignment boundary before allocating memory or
212   //  can request that memory be allocated at a certain address that is aleady aligned).
213   //
214   TotalPages = Pages + (Alignment <= EFI_PAGE_SIZE ? 0 : EFI_SIZE_TO_PAGES(Alignment));
215   Memory = (EFI_PHYSICAL_ADDRESS) (UINTN) InternalAllocatePages (MemoryType, TotalPages);
216   if (Memory == 0) {
217     DEBUG((DEBUG_INFO, "Out of memory resource! \n"));
218     return NULL;
219   }
220   DEBUG ((DEBUG_INFO, "Allocated Memory unaligned: Address = 0x%LX, Pages = 0x%X, Type = %d \n", Memory, TotalPages, (UINTN) MemoryType));
221 
222   //
223   // Alignment calculation
224   //
225   AlignedMemory = Memory;
226   if (Alignment > EFI_PAGE_SIZE) {
227     AlignedMemory = ALIGN_VALUE (Memory, Alignment);
228   }
229   DEBUG ((DEBUG_INFO, "After aligning to 0x%X bytes: Address = 0x%LX, Pages = 0x%X \n", Alignment, AlignedMemory, Pages));
230 
231   //
232   // In general three HOBs cover the total allocated space.
233   // The aligned portion is covered by the aligned mem HOB and
234   // the unaligned(to be freed) portions before and after the aligned portion are covered by newly created HOBs.
235   //
236   // Before mem HOB covers the region between "Memory" and "AlignedMemory"
237   // Aligned mem HOB covers the region between "AlignedMemory" and "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)"
238   // After mem HOB covers the region between "AlignedMemory + EFI_PAGES_TO_SIZE(Pages)" and "Memory + EFI_PAGES_TO_SIZE(TotalPages)"
239   //
240   // The before or after mem HOBs need to be skipped under special cases where the aligned portion
241   // touches either the top or bottom of the original allocated space.
242   //
243   SkipBeforeMemHob = FALSE;
244   SkipAfterMemHob  = FALSE;
245   if (Memory == AlignedMemory) {
246     SkipBeforeMemHob = TRUE;
247   }
248   if ((Memory + EFI_PAGES_TO_SIZE(TotalPages)) == (AlignedMemory + EFI_PAGES_TO_SIZE(Pages))) {
249     //
250     // This condition is never met in the current implementation.
251     // There is always some after-mem since the overhead mem(used in TotalPages)
252     // is no less than Alignment.
253     //
254     SkipAfterMemHob = TRUE;
255   }
256 
257   //
258   // Search for the mem HOB referring to the original(unaligned) allocation
259   // and update the size and type if needed.
260   //
261   Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
262   while (Hob.Raw != NULL) {
263     if (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == Memory) {
264       break;
265     }
266     Hob.Raw = GET_NEXT_HOB (Hob);
267     Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw);
268   }
269   ASSERT (Hob.Raw != NULL);
270   if (SkipBeforeMemHob) {
271     //
272     // Use this HOB as aligned mem HOB as there is no portion before it.
273     //
274     HobLength = EFI_PAGES_TO_SIZE(Pages);
275     Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength;
276   } else {
277     //
278     // Use this HOB as before mem HOB and create a new HOB for the aligned portion
279     //
280     HobLength = (AlignedMemory - Memory);
281     Hob.MemoryAllocation->AllocDescriptor.MemoryLength = HobLength;
282     Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiConventionalMemory;
283   }
284 
285   HobBaseAddress = Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress;
286   HobMemoryType = Hob.MemoryAllocation->AllocDescriptor.MemoryType;
287 
288   //
289   // Build the aligned mem HOB if needed
290   //
291   if (!SkipBeforeMemHob) {
292     DEBUG((DEBUG_INFO, "Updated before-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",
293       HobBaseAddress, HobLength, (UINTN) HobMemoryType));
294 
295     HobBaseAddress = AlignedMemory;
296     HobLength = EFI_PAGES_TO_SIZE(Pages);
297     HobMemoryType = MemoryType;
298 
299     BuildMemoryAllocationHob (
300       HobBaseAddress,
301       HobLength,
302       HobMemoryType
303       );
304 
305     DEBUG((DEBUG_INFO, "Created aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",
306       HobBaseAddress, HobLength, (UINTN) HobMemoryType));
307   } else {
308     if (HobBaseAddress != 0) {
309       DEBUG((DEBUG_INFO, "Updated aligned-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",
310         HobBaseAddress, HobLength, (UINTN) HobMemoryType));
311     }
312   }
313 
314 
315   //
316   // Build the after mem HOB if needed
317   //
318   if (!SkipAfterMemHob) {
319     HobBaseAddress = AlignedMemory + EFI_PAGES_TO_SIZE(Pages);
320     HobLength = (Memory + EFI_PAGES_TO_SIZE(TotalPages)) - (AlignedMemory + EFI_PAGES_TO_SIZE(Pages));
321     HobMemoryType = EfiConventionalMemory;
322 
323     BuildMemoryAllocationHob (
324       HobBaseAddress,
325       HobLength,
326       HobMemoryType
327       );
328 
329     DEBUG((DEBUG_INFO, "Created after-mem HOB with BaseAddress = %LX, Length = %LX, MemoryType = %d \n",
330       HobBaseAddress, HobLength, (UINTN) HobMemoryType));
331   }
332 
333   return (VOID *) (UINTN) AlignedMemory;
334 }
335 
336 /**
337   Allocates one or more 4KB pages of type EfiBootServicesData at a specified alignment.
338 
339   Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an
340   alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
341   returned.  If there is not enough memory at the specified alignment remaining to satisfy the
342   request, then NULL is returned.
343 
344   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
345   If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
346 
347   @param  Pages                 The number of 4 KB pages to allocate.
348   @param  Alignment             The requested alignment of the allocation.
349                                 Must be a power of two.
350                                 If Alignment is zero, then byte alignment is used.
351 
352   @return A pointer to the allocated buffer or NULL if allocation fails.
353 
354 **/
355 VOID *
356 EFIAPI
AllocateAlignedPages(IN UINTN Pages,IN UINTN Alignment)357 AllocateAlignedPages (
358   IN UINTN  Pages,
359   IN UINTN  Alignment
360   )
361 {
362   return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment);
363 }
364 
365 /**
366   Allocates one or more 4KB pages of type EfiRuntimeServicesData at a specified alignment.
367 
368   Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an
369   alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
370   returned.  If there is not enough memory at the specified alignment remaining to satisfy the
371   request, then NULL is returned.
372 
373   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
374   If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
375 
376   @param  Pages                 The number of 4 KB pages to allocate.
377   @param  Alignment             The requested alignment of the allocation.
378                                 Must be a power of two.
379                                 If Alignment is zero, then byte alignment is used.
380 
381   @return A pointer to the allocated buffer or NULL if allocation fails.
382 
383 **/
384 VOID *
385 EFIAPI
AllocateAlignedRuntimePages(IN UINTN Pages,IN UINTN Alignment)386 AllocateAlignedRuntimePages (
387   IN UINTN  Pages,
388   IN UINTN  Alignment
389   )
390 {
391   return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment);
392 }
393 
394 /**
395   Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment.
396 
397   Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType with an
398   alignment specified by Alignment.  The allocated buffer is returned.  If Pages is 0, then NULL is
399   returned.  If there is not enough memory at the specified alignment remaining to satisfy the
400   request, then NULL is returned.
401 
402   If Alignment is not a power of two and Alignment is not zero, then ASSERT().
403   If Pages plus EFI_SIZE_TO_PAGES (Alignment) overflows, then ASSERT().
404 
405   @param  Pages                 The number of 4 KB pages to allocate.
406   @param  Alignment             The requested alignment of the allocation.
407                                 Must be a power of two.
408                                 If Alignment is zero, then byte alignment is used.
409 
410   @return A pointer to the allocated buffer or NULL if allocation fails.
411 
412 **/
413 VOID *
414 EFIAPI
AllocateAlignedReservedPages(IN UINTN Pages,IN UINTN Alignment)415 AllocateAlignedReservedPages (
416   IN UINTN  Pages,
417   IN UINTN  Alignment
418   )
419 {
420   return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment);
421 }
422 
423 /**
424   Frees one or more 4KB pages that were previously allocated with one of the aligned page
425   allocation functions in the Memory Allocation Library.
426 
427   Frees the number of 4KB pages specified by Pages from the buffer specified by Buffer.  Buffer
428   must have been allocated on a previous call to the aligned page allocation services of the Memory
429   Allocation Library.  If it is not possible to free allocated pages, then this function will
430   perform no actions.
431 
432   If Buffer was not allocated with an aligned page allocation function in the Memory Allocation
433   Library, then ASSERT().
434   If Pages is zero, then ASSERT().
435 
436   @param  Buffer                The pointer to the buffer of pages to free.
437   @param  Pages                 The number of 4 KB pages to free.
438 
439 **/
440 VOID
441 EFIAPI
FreeAlignedPages(IN VOID * Buffer,IN UINTN Pages)442 FreeAlignedPages (
443   IN VOID   *Buffer,
444   IN UINTN  Pages
445   )
446 {
447   ASSERT (Pages != 0);
448   //
449   // PEI phase does not support to free pages, so leave it as NOP.
450   //
451 }
452 
453 /**
454   Allocates a buffer of a certain pool type.
455 
456   Allocates the number bytes specified by AllocationSize of a certain pool type and returns a
457   pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
458   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
459 
460   @param  MemoryType            The type of memory to allocate.
461   @param  AllocationSize        The number of bytes to allocate.
462 
463   @return A pointer to the allocated buffer or NULL if allocation fails.
464 
465 **/
466 VOID *
InternalAllocatePool(IN EFI_MEMORY_TYPE MemoryType,IN UINTN AllocationSize)467 InternalAllocatePool (
468   IN EFI_MEMORY_TYPE  MemoryType,
469   IN UINTN            AllocationSize
470   )
471 {
472   //
473   // If we need lots of small runtime/reserved memory type from PEI in the future,
474   // we can consider providing a more complex algorithm that allocates runtime pages and
475   // provide pool allocations from those pages.
476   //
477   return InternalAllocatePages (MemoryType, EFI_SIZE_TO_PAGES (AllocationSize));
478 }
479 
480 /**
481   Allocates a buffer of type EfiBootServicesData.
482 
483   Allocates the number bytes specified by AllocationSize of type EfiBootServicesData and returns a
484   pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
485   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
486 
487   @param  AllocationSize        The number of bytes to allocate.
488 
489   @return A pointer to the allocated buffer or NULL if allocation fails.
490 
491 **/
492 VOID *
493 EFIAPI
AllocatePool(IN UINTN AllocationSize)494 AllocatePool (
495   IN UINTN  AllocationSize
496   )
497 {
498   EFI_STATUS        Status;
499   VOID              *Buffer;
500 
501   Status = PeiServicesAllocatePool (AllocationSize, &Buffer);
502   if (EFI_ERROR (Status)) {
503     Buffer = NULL;
504   }
505   return Buffer;
506 }
507 
508 /**
509   Allocates a buffer of type EfiRuntimeServicesData.
510 
511   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData and returns
512   a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
513   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
514 
515   @param  AllocationSize        The number of bytes to allocate.
516 
517   @return A pointer to the allocated buffer or NULL if allocation fails.
518 
519 **/
520 VOID *
521 EFIAPI
AllocateRuntimePool(IN UINTN AllocationSize)522 AllocateRuntimePool (
523   IN UINTN  AllocationSize
524   )
525 {
526   return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize);
527 }
528 
529 /**
530   Allocates a buffer of type EfiReservedMemoryType.
531 
532   Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType and returns
533   a pointer to the allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is
534   returned.  If there is not enough memory remaining to satisfy the request, then NULL is returned.
535 
536   @param  AllocationSize        The number of bytes to allocate.
537 
538   @return A pointer to the allocated buffer or NULL if allocation fails.
539 
540 **/
541 VOID *
542 EFIAPI
AllocateReservedPool(IN UINTN AllocationSize)543 AllocateReservedPool (
544   IN UINTN  AllocationSize
545   )
546 {
547   return InternalAllocatePool (EfiReservedMemoryType, AllocationSize);
548 }
549 
550 /**
551   Allocates and zeros a buffer of a certain pool type.
552 
553   Allocates the number bytes specified by AllocationSize of a certain pool type, clears the buffer
554   with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a valid
555   buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the request,
556   then NULL is returned.
557 
558   @param  PoolType              The type of memory to allocate.
559   @param  AllocationSize        The number of bytes to allocate and zero.
560 
561   @return A pointer to the allocated buffer or NULL if allocation fails.
562 
563 **/
564 VOID *
InternalAllocateZeroPool(IN EFI_MEMORY_TYPE PoolType,IN UINTN AllocationSize)565 InternalAllocateZeroPool (
566   IN EFI_MEMORY_TYPE  PoolType,
567   IN UINTN            AllocationSize
568   )
569 {
570   VOID  *Memory;
571 
572   Memory = InternalAllocatePool (PoolType, AllocationSize);
573   if (Memory != NULL) {
574     Memory = ZeroMem (Memory, AllocationSize);
575   }
576   return Memory;
577 }
578 
579 /**
580   Allocates and zeros a buffer of type EfiBootServicesData.
581 
582   Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, clears the
583   buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
584   valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
585   request, then NULL is returned.
586 
587   @param  AllocationSize        The number of bytes to allocate and zero.
588 
589   @return A pointer to the allocated buffer or NULL if allocation fails.
590 
591 **/
592 VOID *
593 EFIAPI
AllocateZeroPool(IN UINTN AllocationSize)594 AllocateZeroPool (
595   IN UINTN  AllocationSize
596   )
597 {
598   VOID  *Memory;
599 
600   Memory = AllocatePool (AllocationSize);
601   if (Memory != NULL) {
602     Memory = ZeroMem (Memory, AllocationSize);
603   }
604   return Memory;
605 }
606 
607 /**
608   Allocates and zeros a buffer of type EfiRuntimeServicesData.
609 
610   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, clears the
611   buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
612   valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
613   request, then NULL is returned.
614 
615   @param  AllocationSize        The number of bytes to allocate and zero.
616 
617   @return A pointer to the allocated buffer or NULL if allocation fails.
618 
619 **/
620 VOID *
621 EFIAPI
AllocateRuntimeZeroPool(IN UINTN AllocationSize)622 AllocateRuntimeZeroPool (
623   IN UINTN  AllocationSize
624   )
625 {
626   return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize);
627 }
628 
629 /**
630   Allocates and zeros a buffer of type EfiReservedMemoryType.
631 
632   Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, clears the
633   buffer with zeros, and returns a pointer to the allocated buffer.  If AllocationSize is 0, then a
634   valid buffer of 0 size is returned.  If there is not enough memory remaining to satisfy the
635   request, then NULL is returned.
636 
637   @param  AllocationSize        The number of bytes to allocate and zero.
638 
639   @return A pointer to the allocated buffer or NULL if allocation fails.
640 
641 **/
642 VOID *
643 EFIAPI
AllocateReservedZeroPool(IN UINTN AllocationSize)644 AllocateReservedZeroPool (
645   IN UINTN  AllocationSize
646   )
647 {
648   return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize);
649 }
650 
651 /**
652   Copies a buffer to an allocated buffer of a certain pool type.
653 
654   Allocates the number bytes specified by AllocationSize of a certain pool type, copies
655   AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
656   allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
657   is not enough memory remaining to satisfy the request, then NULL is returned.
658   If Buffer is NULL, then ASSERT().
659   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
660 
661   @param  PoolType              The type of pool to allocate.
662   @param  AllocationSize        The number of bytes to allocate and zero.
663   @param  Buffer                The buffer to copy to the allocated buffer.
664 
665   @return A pointer to the allocated buffer or NULL if allocation fails.
666 
667 **/
668 VOID *
InternalAllocateCopyPool(IN EFI_MEMORY_TYPE PoolType,IN UINTN AllocationSize,IN CONST VOID * Buffer)669 InternalAllocateCopyPool (
670   IN EFI_MEMORY_TYPE  PoolType,
671   IN UINTN            AllocationSize,
672   IN CONST VOID       *Buffer
673   )
674 {
675   VOID  *Memory;
676 
677   ASSERT (Buffer != NULL);
678   ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));
679 
680   Memory = InternalAllocatePool (PoolType, AllocationSize);
681   if (Memory != NULL) {
682      Memory = CopyMem (Memory, Buffer, AllocationSize);
683   }
684   return Memory;
685 }
686 
687 /**
688   Copies a buffer to an allocated buffer of type EfiBootServicesData.
689 
690   Allocates the number bytes specified by AllocationSize of type EfiBootServicesData, copies
691   AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
692   allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
693   is not enough memory remaining to satisfy the request, then NULL is returned.
694 
695   If Buffer is NULL, then ASSERT().
696   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
697 
698   @param  AllocationSize        The number of bytes to allocate and zero.
699   @param  Buffer                The buffer to copy to the allocated buffer.
700 
701   @return A pointer to the allocated buffer or NULL if allocation fails.
702 
703 **/
704 VOID *
705 EFIAPI
AllocateCopyPool(IN UINTN AllocationSize,IN CONST VOID * Buffer)706 AllocateCopyPool (
707   IN UINTN       AllocationSize,
708   IN CONST VOID  *Buffer
709   )
710 {
711   VOID  *Memory;
712 
713   ASSERT (Buffer != NULL);
714   ASSERT (AllocationSize <= (MAX_ADDRESS - (UINTN) Buffer + 1));
715 
716   Memory = AllocatePool (AllocationSize);
717   if (Memory != NULL) {
718      Memory = CopyMem (Memory, Buffer, AllocationSize);
719   }
720   return Memory;
721 }
722 
723 /**
724   Copies a buffer to an allocated buffer of type EfiRuntimeServicesData.
725 
726   Allocates the number bytes specified by AllocationSize of type EfiRuntimeServicesData, copies
727   AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
728   allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
729   is not enough memory remaining to satisfy the request, then NULL is returned.
730 
731   If Buffer is NULL, then ASSERT().
732   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
733 
734   @param  AllocationSize        The number of bytes to allocate and zero.
735   @param  Buffer                The buffer to copy to the allocated buffer.
736 
737   @return A pointer to the allocated buffer or NULL if allocation fails.
738 
739 **/
740 VOID *
741 EFIAPI
AllocateRuntimeCopyPool(IN UINTN AllocationSize,IN CONST VOID * Buffer)742 AllocateRuntimeCopyPool (
743   IN UINTN       AllocationSize,
744   IN CONST VOID  *Buffer
745   )
746 {
747   return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer);
748 }
749 
750 /**
751   Copies a buffer to an allocated buffer of type EfiReservedMemoryType.
752 
753   Allocates the number bytes specified by AllocationSize of type EfiReservedMemoryType, copies
754   AllocationSize bytes from Buffer to the newly allocated buffer, and returns a pointer to the
755   allocated buffer.  If AllocationSize is 0, then a valid buffer of 0 size is returned.  If there
756   is not enough memory remaining to satisfy the request, then NULL is returned.
757 
758   If Buffer is NULL, then ASSERT().
759   If AllocationSize is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
760 
761   @param  AllocationSize        The number of bytes to allocate and zero.
762   @param  Buffer                The buffer to copy to the allocated buffer.
763 
764   @return A pointer to the allocated buffer or NULL if allocation fails.
765 
766 **/
767 VOID *
768 EFIAPI
AllocateReservedCopyPool(IN UINTN AllocationSize,IN CONST VOID * Buffer)769 AllocateReservedCopyPool (
770   IN UINTN       AllocationSize,
771   IN CONST VOID  *Buffer
772   )
773 {
774   return InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer);
775 }
776 
777 /**
778   Reallocates a buffer of a specified memory type.
779 
780   Allocates and zeros the number bytes specified by NewSize from memory of the type
781   specified by PoolType.  If OldBuffer is not NULL, then the smaller of OldSize and
782   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
783   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
784   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
785   enough memory remaining to satisfy the request, then NULL is returned.
786 
787   If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
788   is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
789 
790   @param  PoolType       The type of pool to allocate.
791   @param  OldSize        The size, in bytes, of OldBuffer.
792   @param  NewSize        The size, in bytes, of the buffer to reallocate.
793   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an
794                          optional parameter that may be NULL.
795 
796   @return A pointer to the allocated buffer or NULL if allocation fails.
797 
798 **/
799 VOID *
InternalReallocatePool(IN EFI_MEMORY_TYPE PoolType,IN UINTN OldSize,IN UINTN NewSize,IN VOID * OldBuffer OPTIONAL)800 InternalReallocatePool (
801   IN EFI_MEMORY_TYPE  PoolType,
802   IN UINTN            OldSize,
803   IN UINTN            NewSize,
804   IN VOID             *OldBuffer  OPTIONAL
805   )
806 {
807   VOID  *NewBuffer;
808 
809   NewBuffer = InternalAllocateZeroPool (PoolType, NewSize);
810   if (NewBuffer != NULL && OldBuffer != NULL) {
811     CopyMem (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
812     FreePool (OldBuffer);
813   }
814   return NewBuffer;
815 }
816 
817 /**
818   Reallocates a buffer of type EfiBootServicesData.
819 
820   Allocates and zeros the number bytes specified by NewSize from memory of type
821   EfiBootServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and
822   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
823   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
824   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
825   enough memory remaining to satisfy the request, then NULL is returned.
826 
827   If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
828   is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
829 
830   @param  OldSize        The size, in bytes, of OldBuffer.
831   @param  NewSize        The size, in bytes, of the buffer to reallocate.
832   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
833                          parameter that may be NULL.
834 
835   @return A pointer to the allocated buffer or NULL if allocation fails.
836 
837 **/
838 VOID *
839 EFIAPI
ReallocatePool(IN UINTN OldSize,IN UINTN NewSize,IN VOID * OldBuffer OPTIONAL)840 ReallocatePool (
841   IN UINTN  OldSize,
842   IN UINTN  NewSize,
843   IN VOID   *OldBuffer  OPTIONAL
844   )
845 {
846   return InternalReallocatePool (EfiBootServicesData, OldSize, NewSize, OldBuffer);
847 }
848 
849 /**
850   Reallocates a buffer of type EfiRuntimeServicesData.
851 
852   Allocates and zeros the number bytes specified by NewSize from memory of type
853   EfiRuntimeServicesData.  If OldBuffer is not NULL, then the smaller of OldSize and
854   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
855   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
856   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
857   enough memory remaining to satisfy the request, then NULL is returned.
858 
859   If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
860   is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
861 
862   @param  OldSize        The size, in bytes, of OldBuffer.
863   @param  NewSize        The size, in bytes, of the buffer to reallocate.
864   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an optional
865                          parameter that may be NULL.
866 
867   @return A pointer to the allocated buffer or NULL if allocation fails.
868 
869 **/
870 VOID *
871 EFIAPI
ReallocateRuntimePool(IN UINTN OldSize,IN UINTN NewSize,IN VOID * OldBuffer OPTIONAL)872 ReallocateRuntimePool (
873   IN UINTN  OldSize,
874   IN UINTN  NewSize,
875   IN VOID   *OldBuffer  OPTIONAL
876   )
877 {
878   return InternalReallocatePool (EfiRuntimeServicesData, OldSize, NewSize, OldBuffer);
879 }
880 
881 /**
882   Reallocates a buffer of type EfiReservedMemoryType.
883 
884   Allocates and zeros the number bytes specified by NewSize from memory of type
885   EfiReservedMemoryType.  If OldBuffer is not NULL, then the smaller of OldSize and
886   NewSize bytes are copied from OldBuffer to the newly allocated buffer, and
887   OldBuffer is freed.  A pointer to the newly allocated buffer is returned.
888   If NewSize is 0, then a valid buffer of 0 size is  returned.  If there is not
889   enough memory remaining to satisfy the request, then NULL is returned.
890 
891   If the allocation of the new buffer is successful and the smaller of NewSize and OldSize
892   is greater than (MAX_ADDRESS - OldBuffer + 1), then ASSERT().
893 
894   @param  OldSize        The size, in bytes, of OldBuffer.
895   @param  NewSize        The size, in bytes, of the buffer to reallocate.
896   @param  OldBuffer      The buffer to copy to the allocated buffer.  This is an
897                          optional parameter that may be NULL.
898 
899   @return A pointer to the allocated buffer or NULL if allocation fails.
900 
901 **/
902 VOID *
903 EFIAPI
ReallocateReservedPool(IN UINTN OldSize,IN UINTN NewSize,IN VOID * OldBuffer OPTIONAL)904 ReallocateReservedPool (
905   IN UINTN  OldSize,
906   IN UINTN  NewSize,
907   IN VOID   *OldBuffer  OPTIONAL
908   )
909 {
910   return InternalReallocatePool (EfiReservedMemoryType, OldSize, NewSize, OldBuffer);
911 }
912 
913 /**
914   Frees a buffer that was previously allocated with one of the pool allocation functions in the
915   Memory Allocation Library.
916 
917   Frees the buffer specified by Buffer.  Buffer must have been allocated on a previous call to the
918   pool allocation services of the Memory Allocation Library.  If it is not possible to free pool
919   resources, then this function will perform no actions.
920 
921   If Buffer was not allocated with a pool allocation function in the Memory Allocation Library,
922   then ASSERT().
923 
924   @param  Buffer                The pointer to the buffer to free.
925 
926 **/
927 VOID
928 EFIAPI
FreePool(IN VOID * Buffer)929 FreePool (
930   IN VOID   *Buffer
931   )
932 {
933   //
934   // PEI phase does not support to free pool, so leave it as NOP.
935   //
936 }
937 
938 
939