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