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