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