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**/
40VOID *
41InternalAllocatePages (
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**/
74VOID *
75EFIAPI
76AllocatePages (
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**/
96VOID *
97EFIAPI
98AllocateRuntimePages (
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**/
118VOID *
119EFIAPI
120AllocateReservedPages (
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**/
144VOID
145EFIAPI
146FreePages (
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**/
176VOID *
177InternalAllocateAlignedPages (
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**/
355VOID *
356EFIAPI
357AllocateAlignedPages (
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**/
384VOID *
385EFIAPI
386AllocateAlignedRuntimePages (
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**/
413VOID *
414EFIAPI
415AllocateAlignedReservedPages (
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**/
440VOID
441EFIAPI
442FreeAlignedPages (
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**/
466VOID *
467InternalAllocatePool (
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**/
492VOID *
493EFIAPI
494AllocatePool (
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**/
520VOID *
521EFIAPI
522AllocateRuntimePool (
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**/
541VOID *
542EFIAPI
543AllocateReservedPool (
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**/
564VOID *
565InternalAllocateZeroPool (
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**/
592VOID *
593EFIAPI
594AllocateZeroPool (
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**/
620VOID *
621EFIAPI
622AllocateRuntimeZeroPool (
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**/
642VOID *
643EFIAPI
644AllocateReservedZeroPool (
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**/
668VOID *
669InternalAllocateCopyPool (
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**/
704VOID *
705EFIAPI
706AllocateCopyPool (
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**/
740VOID *
741EFIAPI
742AllocateRuntimeCopyPool (
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**/
767VOID *
768EFIAPI
769AllocateReservedCopyPool (
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**/
799VOID *
800InternalReallocatePool (
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**/
838VOID *
839EFIAPI
840ReallocatePool (
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**/
870VOID *
871EFIAPI
872ReallocateRuntimePool (
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**/
902VOID *
903EFIAPI
904ReallocateReservedPool (
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**/
927VOID
928EFIAPI
929FreePool (
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