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