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