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