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