]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/SmmMemoryAllocationProfileLib/MemoryAllocationLib.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Library / SmmMemoryAllocationProfileLib / MemoryAllocationLib.c
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
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
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
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 *
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
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
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
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
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 *
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
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
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
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
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 *
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
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
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
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 *
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
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
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
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 *
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
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
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
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 *
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
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
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
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
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 }