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