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